├── .github ├── CMakeLists.txt ├── example_implot.cpp └── workflows │ └── build.yml ├── LICENSE ├── README.md ├── TODO.md ├── implot.cpp ├── implot.h ├── implot_demo.cpp ├── implot_internal.h └── implot_items.cpp /.github/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This build script is not meant for general use, it is for CI use only! 2 | cmake_minimum_required(VERSION 3.0) 3 | project(implot) 4 | 5 | # 6 | # Global options 7 | # 8 | 9 | # Same as Dear ImGui 10 | set(CMAKE_CXX_STANDARD 11) 11 | 12 | # Arch option for linux 13 | if (NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU" AND DEFINED GCC_ARCH) 14 | if ("${GCC_ARCH}" MATCHES "Win32|x86|32") 15 | add_compile_options(-m32) 16 | add_link_options(-m32) 17 | elseif ("${GCC_ARCH}" MATCHES "Win64|x64|64") 18 | add_compile_options(-m64) 19 | add_link_options(-m64) 20 | endif () 21 | endif () 22 | 23 | # Arch option for Mac: arm64 for M1 or x86_64 for intel (32 bits build are deprecated on Mac) 24 | if(APPLE AND DEFINED OSX_ARCH) 25 | if ("${OSX_ARCH}" MATCHES "x86_64") 26 | set(CMAKE_OSX_ARCHITECTURES "x86_64") 27 | elseif ("${OSX_ARCH}" MATCHES "arm64") 28 | set(CMAKE_OSX_ARCHITECTURES "arm64") 29 | else() 30 | message(FATAL_ERROR "Unhandled OSX_ARCH=${OSX_ARCH}") 31 | endif() 32 | endif() 33 | 34 | # 35 | # Dear ImGui library with no backend 36 | # 37 | 38 | set(imgui_sources 39 | ../imgui/imconfig.h 40 | ../imgui/imgui.cpp 41 | ../imgui/imgui.h 42 | ../imgui/imgui_demo.cpp 43 | ../imgui/imgui_draw.cpp 44 | ../imgui/imgui_internal.h 45 | ../imgui/imgui_tables.cpp 46 | ../imgui/imgui_widgets.cpp 47 | ../imgui/imstb_rectpack.h 48 | ../imgui/imstb_textedit.h 49 | ../imgui/imstb_truetype.h 50 | ) 51 | add_library(imgui ${imgui_sources}) 52 | target_include_directories(imgui PUBLIC ../imgui) 53 | 54 | # 55 | # ImPlot library 56 | # 57 | 58 | file(GLOB SOURCE_CODE ../implot*.*) 59 | add_library(implot STATIC ${SOURCE_CODE}) 60 | 61 | if(MSVC) 62 | target_compile_options(implot PRIVATE /W4 /WX) 63 | else() 64 | target_compile_options(implot PRIVATE -Wall -Werror -pedantic) 65 | endif() 66 | 67 | target_include_directories(implot PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) 68 | target_link_libraries(implot PUBLIC imgui) 69 | 70 | if (UNIX) 71 | target_link_libraries(implot PUBLIC m stdc++) 72 | endif() 73 | 74 | # Define supported types via command line: 75 | # - With no choice all types are supported (so that the CI provides support for all known types) 76 | # - with -DIMPLOT_CUSTOM_NUMERIC_TYPES="default" the default set defined in implot_items.cpp is used 77 | # - with -DIMPLOT_CUSTOM_NUMERIC_TYPES="(int)(float)(double)" only int, float and double are supported 78 | if (NOT DEFINED IMPLOT_CUSTOM_NUMERIC_TYPES) 79 | set(IMPLOT_CUSTOM_NUMERIC_TYPES "all") 80 | endif() 81 | if ("${IMPLOT_CUSTOM_NUMERIC_TYPES}" STREQUAL "default") 82 | message("==== Compiling for default types ====") 83 | elseif("${IMPLOT_CUSTOM_NUMERIC_TYPES}" STREQUAL "all") 84 | message("==== Compiling for all types ====") 85 | target_compile_definitions(implot PRIVATE "IMPLOT_CUSTOM_NUMERIC_TYPES=(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned long)(signed long long)(unsigned long long)(float)(double)(long double)") 86 | else() 87 | message("==== Compiling for custom types: ${IMPLOT_CUSTOM_NUMERIC_TYPES} ====") 88 | target_compile_definitions(implot PRIVATE "IMPLOT_CUSTOM_NUMERIC_TYPES=${IMPLOT_CUSTOM_NUMERIC_TYPES}") 89 | endif() 90 | 91 | # 92 | # implot example binary application (with no backend) 93 | # 94 | add_executable(example_implot example_implot.cpp) 95 | target_link_libraries(example_implot PRIVATE implot) 96 | -------------------------------------------------------------------------------- /.github/example_implot.cpp: -------------------------------------------------------------------------------- 1 | // Sample app built with Dear ImGui and ImPlot 2 | // This app uses implot and imgui, but does not output to any backend! It only serves as a proof that an app can be built, linked, and run. 3 | 4 | #include "imgui.h" 5 | #include "implot.h" 6 | #include "stdio.h" 7 | 8 | int main(int, char**) 9 | { 10 | printf("sample_implot: start\n"); 11 | 12 | IMGUI_CHECKVERSION(); 13 | ImGui::CreateContext(); 14 | ImPlot::CreateContext(); 15 | 16 | // Additional imgui initialization needed when no backend is present 17 | ImGui::GetIO().DisplaySize = ImVec2(400.f, 400.f); 18 | ImGui::GetIO().Fonts->Build(); 19 | 20 | // Render 500 frames 21 | for(int counter = 0; counter < 500; ++counter) 22 | { 23 | ImGui::NewFrame(); 24 | 25 | if (ImGui::Begin("Hello, world!")) 26 | { 27 | ImGui::Text("Hello again"); 28 | 29 | if (ImPlot::BeginPlot("My Plot")) 30 | { 31 | static double values[] = {1., 3., 5.}; 32 | ImPlot::PlotLine("Values", values, 3); 33 | ImPlot::EndPlot(); 34 | } 35 | 36 | #ifdef IMPLOT_INSTANTIATE_ALL_NUMERIC_TYPES 37 | if (ImPlot::BeginPlot("My Plot (long double)")) 38 | { 39 | static long double values[] = {1., 3., 5.}; 40 | ImPlot::PlotLine("Values", values, 3); 41 | ImPlot::EndPlot(); 42 | } 43 | #endif 44 | 45 | ImGui::End(); 46 | } 47 | 48 | ImGui::Render(); 49 | } 50 | 51 | ImPlot::DestroyContext(); 52 | ImGui::DestroyContext(); 53 | printf("sample_implot: end\n"); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | Linux: 9 | runs-on: ubuntu-22.04 10 | 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | build_type: 15 | - debug 16 | - release 17 | compiler: 18 | - gcc 19 | - clang 20 | arch: 21 | - x86 22 | - x64 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: actions/checkout@v3 28 | with: 29 | repository: ocornut/imgui 30 | path: imgui 31 | 32 | - name: Dependencies 33 | run: sudo apt-get install g++-multilib 34 | 35 | - name: Configure 36 | run: cmake -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_C_COMPILER=${{ matrix.compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DGCC_ARCH=${{ matrix.arch }} -B cmake-build -S .github 37 | 38 | - name: Build 39 | run: cmake --build cmake-build --parallel $(nproc) 40 | 41 | - name: Run 42 | run: | 43 | file cmake-build/example_implot 44 | cmake-build/example_implot 45 | 46 | MacOS: 47 | runs-on: macos-11 48 | 49 | strategy: 50 | fail-fast: false 51 | matrix: 52 | build_type: 53 | - debug 54 | - release 55 | arch: 56 | - x86_64 57 | - arm64 58 | 59 | steps: 60 | - uses: actions/checkout@v3 61 | 62 | - uses: actions/checkout@v3 63 | with: 64 | repository: ocornut/imgui 65 | path: imgui 66 | 67 | - name: Configure 68 | shell: bash 69 | run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DOSX_ARCH=${{ matrix.arch }} -B cmake-build -S .github 70 | 71 | - name: Build 72 | shell: bash 73 | run: cmake --build cmake-build --parallel $(sysctl -n hw.ncpu) 74 | 75 | - name: Run 76 | if: matrix.arch == 'x86_64' # github's CI hosts seem to be running intel and can not run ARM 77 | run: | 78 | file cmake-build/example_implot 79 | cmake-build/example_implot 80 | 81 | Windows_MSVC: 82 | runs-on: windows-2022 83 | 84 | strategy: 85 | fail-fast: false 86 | matrix: 87 | build_type: 88 | - debug 89 | - release 90 | arch: 91 | - Win32 92 | - x64 93 | 94 | steps: 95 | - uses: actions/checkout@v3 96 | 97 | - uses: actions/checkout@v3 98 | with: 99 | repository: ocornut/imgui 100 | path: imgui 101 | 102 | - name: Configure 103 | shell: bash 104 | run: cmake -G 'Visual Studio 17 2022' -A ${{ matrix.arch }} -B cmake-build -S .github 105 | 106 | - name: Build 107 | shell: bash 108 | run: cmake --build cmake-build -- -p:Configuration=${{ matrix.build_type }} -maxcpucount:$NUMBER_OF_PROCESSORS 109 | 110 | - name: Run 111 | run: .\cmake-build\${{matrix.build_type}}\example_implot.exe 112 | 113 | Windows_MingW: # MingW on Github CI does not fully support 32 bits: link fails when it tries to link 64 bits system libraries. 114 | runs-on: windows-2022 115 | 116 | strategy: 117 | fail-fast: false 118 | matrix: 119 | build_type: 120 | - debug 121 | - release 122 | arch: 123 | - x64 124 | # - Win32 125 | 126 | steps: 127 | - uses: actions/checkout@v3 128 | 129 | - uses: actions/checkout@v3 130 | with: 131 | repository: ocornut/imgui 132 | path: imgui 133 | 134 | - name: Configure 135 | shell: bash 136 | run: cmake -G 'MinGW Makefiles' -DGCC_ARCH=${{ matrix.arch }} -B cmake-build -S .github 137 | 138 | - name: Build 139 | shell: bash 140 | run: cmake --build cmake-build --parallel $NUMBER_OF_PROCESSORS 141 | 142 | - name: Run (MingW) 143 | run: .\cmake-build\example_implot.exe 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImPlot 2 | ImPlot is an immediate mode, GPU accelerated plotting library for [Dear ImGui](https://github.com/ocornut/imgui). It aims to provide a first-class API that ImGui fans will love. ImPlot is well suited for visualizing program data in real-time or creating interactive plots, and requires minimal code to integrate. Just like ImGui, it does not burden the end user with GUI state management, avoids STL containers and C++ headers, and has no external dependencies except for ImGui itself. 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ## Features 16 | 17 | - GPU accelerated rendering 18 | - multiple plot types: 19 | - line plots 20 | - shaded plots 21 | - scatter plots 22 | - vertical/horizontal/stacked bars graphs 23 | - vertical/horizontal error bars 24 | - stem plots 25 | - stair plots 26 | - pie charts 27 | - heatmap charts 28 | - 1D/2D histograms 29 | - images 30 | - and more likely to come 31 | - mix/match multiple plot items on a single plot 32 | - configurable axes ranges and scaling (linear/log) 33 | - subplots 34 | - time formatted x-axes (US formatted or ISO 8601) 35 | - reversible and lockable axes 36 | - multiple x-axes and y-axes 37 | - controls for zooming, panning, box selection, and auto-fitting data 38 | - controls for creating persistent query ranges (see demo) 39 | - several plot styling options: 10 marker types, adjustable marker sizes, line weights, outline colors, fill colors, etc. 40 | - 16 built-in colormaps and support for and user-added colormaps 41 | - optional plot titles, axis labels, and grid labels 42 | - optional and configurable legends with toggle buttons to quickly show/hide plot items 43 | - default styling based on current ImGui theme, or completely custom plot styles 44 | - customizable data getters and data striding (just like ImGui:PlotLine) 45 | - accepts data as float, double, and 8, 16, 32, and 64-bit signed/unsigned integral types 46 | - and more! (see Announcements [2022](https://github.com/epezent/implot/discussions/370)/[2021](https://github.com/epezent/implot/issues/168)/[2020](https://github.com/epezent/implot/issues/48)) 47 | 48 | ## Usage 49 | 50 | The API is used just like any other ImGui `BeginX`/`EndX` pair. First, start a new plot with `ImPlot::BeginPlot()`. Next, plot as many items as you want with the provided `PlotX` functions (e.g. `PlotLine()`, `PlotBars()`, `PlotScatter()`, etc). Finally, wrap things up with a call to `ImPlot::EndPlot()`. That's it! 51 | 52 | ```cpp 53 | int bar_data[11] = ...; 54 | float x_data[1000] = ...; 55 | float y_data[1000] = ...; 56 | 57 | ImGui::Begin("My Window"); 58 | if (ImPlot::BeginPlot("My Plot")) { 59 | ImPlot::PlotBars("My Bar Plot", bar_data, 11); 60 | ImPlot::PlotLine("My Line Plot", x_data, y_data, 1000); 61 | ... 62 | ImPlot::EndPlot(); 63 | } 64 | ImGui::End(); 65 | ``` 66 | 67 | ![Usage](https://raw.githubusercontent.com/wiki/epezent/implot/screenshots3/example.PNG) 68 | 69 | 70 | Of course, there's much more you can do with ImPlot... 71 | 72 | ## Demos 73 | 74 | A comprehensive example of ImPlot's features can be found in `implot_demo.cpp`. Add this file to your sources and call `ImPlot::ShowDemoWindow()` somewhere in your update loop. You are encouraged to use this file as a reference when needing to implement various plot types. The demo is always updated to show new plot types and features as they are added, so check back with each release! 75 | 76 | An online version of the demo is hosted [here](https://traineq.org/implot_demo/src/implot_demo.html). You can view the plots and the source code that generated them. Note that this demo may not always be up to date and is not as performant as a desktop implementation, but it should give you a general taste of what's possible with ImPlot. Special thanks to [pthom](https://github.com/pthom) for creating and hosting this! 77 | 78 | More sophisticated demos requiring lengthier code and/or third-party libraries can be found in a separate repository: [implot_demos](https://github.com/epezent/implot_demos). Here, you will find advanced signal processing and ImPlot usage in action. Please read the `Contributing` section of that repository if you have an idea for a new demo! 79 | 80 | ## Integration 81 | 82 | 0) Set up an [ImGui](https://github.com/ocornut/imgui) environment if you don't already have one. 83 | 1) Add `implot.h`, `implot_internal.h`, `implot.cpp`, `implot_items.cpp` and optionally `implot_demo.cpp` to your sources. Alternatively, you can get ImPlot using [vcpkg](https://github.com/microsoft/vcpkg/tree/master/ports/implot). 84 | 2) Create and destroy an `ImPlotContext` wherever you do so for your `ImGuiContext`: 85 | 86 | ```cpp 87 | ImGui::CreateContext(); 88 | ImPlot::CreateContext(); 89 | ... 90 | ImPlot::DestroyContext(); 91 | ImGui::DestroyContext(); 92 | ``` 93 | 94 | You should be good to go! 95 | 96 | ## Installing ImPlot using vcpkg 97 | 98 | You can download and install ImPlot using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: 99 | 100 | ```bash 101 | git clone https://github.com/Microsoft/vcpkg.git 102 | cd vcpkg 103 | ./bootstrap-vcpkg.sh 104 | ./vcpkg integrate install 105 | ./vcpkg install implot 106 | ``` 107 | 108 | The ImPlot port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. 109 | 110 | ## Extremely Important Note 111 | 112 | Dear ImGui uses **16-bit indexing by default**, so high-density ImPlot widgets like `ImPlot::PlotHeatmap()` may produce too many vertices into `ImDrawList`, which causes an assertion failure and will result in data truncation and/or visual glitches. Therefore, it is **HIGHLY** recommended that you EITHER: 113 | 114 | - **Option 1:** Enable 32-bit indices by uncommenting `#define ImDrawIdx unsigned int` in your ImGui [`imconfig.h`](https://github.com/ocornut/imgui/blob/master/imconfig.h#L89) file. 115 | - **Option 2:** Handle the `ImGuiBackendFlags_RendererHasVtxOffset` flag in your renderer if you must use 16-bit indices. Many of the default ImGui rendering backends already support `ImGuiBackendFlags_RendererHasVtxOffset`. Refer to [this issue](https://github.com/ocornut/imgui/issues/2591) for more information. 116 | 117 | ## FAQ 118 | 119 | **Q: Why?** 120 | 121 | A: ImGui is an incredibly powerful tool for rapid prototyping and development, but provides only limited mechanisms for data visualization. Two dimensional plots are ubiquitous and useful to almost any application. Being able to visualize your data in real-time will give you insight and better understanding of your application. 122 | 123 | **Q: Is ImPlot the right plotting library for me?** 124 | 125 | A: If you're looking to generate publication quality plots and/or export plots to a file, ImPlot is NOT the library for you! ImPlot is geared toward plotting application data at realtime speeds with high levels of interactivity. ImPlot does its best to create pretty plots (indeed, there are quite a few styling options available), but it will always favor function over form. 126 | 127 | **Q: Where is the documentation?** 128 | 129 | A: The API is thoroughly commented in `implot.h`, and the demo in `implot_demo.cpp` should be more than enough to get you started. Also take a look at the [implot_demos](https://github.com/epezent/implot_demos) repository. 130 | 131 | **Q: Is ImPlot suitable for plotting large datasets?** 132 | 133 | A: Yes, within reason. You can plot tens to hundreds of thousands of points without issue, but don't expect millions to be a buttery smooth experience. That said, you can always downsample extremely large datasets by telling ImPlot to stride your data at larger intervals if needed. Also try the experimental `backends` branch which aims to provide GPU acceleration support. 134 | 135 | **Q: What data types can I plot?** 136 | 137 | A: ImPlot plotting functions accept most scalar types: 138 | `float`, `double`, `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`. Arrays of custom structs or classes (e.g. `Vector2f` or similar) are easily passed to ImPlot functions using the built-in striding features (see `implot.h` for documentation), and many plotters provide a "getter" overload which accepts data generating callbacks. You can fully customize the list of accepted types by defining `IMPLOT_CUSTOM_NUMERIC_TYPES` at compile time: see doc in `implot_items.cpp`. 139 | 140 | **Q: Can plot styles be modified?** 141 | 142 | A: Yes. Data colormaps and various styling colors and variables can be pushed/popped or modified permanently on startup. Three default styles are available, as well as an automatic style that attempts to match you ImGui style. 143 | 144 | **Q: Does ImPlot support logarithmic scaling or time formatting?** 145 | 146 | A: Yep! Both logscale and timescale are supported. 147 | 148 | **Q: Does ImPlot support multiple y-axes? x-axes?** 149 | 150 | A: Yes. Up to three x-axes and three y-axes can be enabled. 151 | 152 | **Q: Does ImPlot support [insert plot type]?** 153 | 154 | A: Maybe. Check the demo, gallery, or Announcements ([2020](https://github.com/epezent/implot/issues/48)/[2021](https://github.com/epezent/implot/issues/168))to see if your desired plot type is shown. If not, consider submitting an issue or better yet, a PR! 155 | 156 | **Q: Does ImPlot support 3D plots?** 157 | 158 | A: No, and likely never will since ImGui only deals in 2D rendering. 159 | 160 | **Q: Does ImPlot provide analytic tools?** 161 | 162 | A: Not exactly, but it does give you the ability to query plot sub-ranges, with which you can process your data however you like. 163 | 164 | **Q: Can plots be exported/saved to image?** 165 | 166 | A: Not currently. Use your OS's screen capturing mechanisms if you need to capture a plot. ImPlot is not suitable for rendering publication quality plots; it is only intended to be used as a visualization tool. Post-process your data with MATLAB or matplotlib for these purposes. 167 | 168 | **Q: Why are my plot lines showing aliasing?** 169 | 170 | A: You probably need to enable `ImGuiStyle::AntiAliasedLinesUseTex` (or possibly `ImGuiStyle:AntiAliasedLines`). If those settings are already enabled, then you must ensure your backend supports texture based anti-aliasing (i.e. uses bilinear sampling). Most of the default ImGui backends support this feature out of the box. Learn more [here](https://github.com/ocornut/imgui/issues/3245). Alternatively, you can enable MSAA at the application level if your hardware supports it (4x should do). 171 | 172 | **Q: Can I compile ImPlot as a dynamic library?** 173 | 174 | A: Like ImGui, it is recommended that you compile and link ImPlot as a *static* library or directly as a part of your sources. However, if you must and are compiling ImPlot and ImGui as separate DLLs, make sure you set the current *ImGui* context with `ImPlot::SetImGuiContext(ImGuiContext* ctx)`. This ensures that global ImGui variables are correctly shared across the DLL boundary. 175 | 176 | **Q: Can ImPlot be used with other languages/bindings?** 177 | 178 | A: Yes, you can use the generated C binding, [cimplot](https://github.com/cimgui/cimplot) with most high level languages. [DearPyGui](https://github.com/hoffstadt/DearPyGui) provides a Python wrapper, among other things. [DearImGui/DearImPlot](https://github.com/aybe/DearImGui) provides bindings for .NET. [imgui-java](https://github.com/SpaiR/imgui-java) provides bindings for Java. [ImPlot.jl](https://github.com/wsphillips/ImPlot.jl) provides bindings for Julia. A Rust binding, [implot-rs](https://github.com/4bb4/implot-rs), is currently in the works. An example using Emscripten can be found [here](https://github.com/pthom/implot_demo). 179 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | The list below represents a combination of high-priority work, nice-to-have features, and random ideas. We make no guarantees that all of this work will be completed or even started. If you see something that you need or would like to have, let us know, or better yet consider submitting a PR for the feature. 2 | 3 | ## API 4 | 5 | ## Axes 6 | 7 | - add flag to remove weekends on Time axis 8 | - pixel space scale (`ImPlotTransform_Display`), normalized space scale (`ImPlotTransform_Axes`), data space scale (`ImPlotTransform_Data`) 9 | - make ImPlotFlags_Equal not a flag -> `SetupEqual(ImPlotAxis x, ImPlotAxis y)` 10 | - allow inverted arguments `SetAxes` to transpose data? 11 | - `SetupAxisColors()` 12 | - `SetupAxisHome()` 13 | 14 | ## Plot Items 15 | 16 | - add `PlotBubbles` (see MATLAB bubble chart) 17 | - add non-zero references for `PlotBars` etc. 18 | - add exploding to `PlotPieChart` (on hover-highlight?) 19 | - fix appearance of `PlotBars` spacing 20 | 21 | ## Styling 22 | 23 | - support gradient and/or colormap sampled fills (e.g. ImPlotFillStyle_) 24 | - API for setting different fonts for plot elements 25 | 26 | ## Colormaps 27 | 28 | - gradient editing tool 29 | - `RemoveColormap` 30 | - `enum ImPlotColorRule_ { Solid, Faded, XValue, YValue, ZValue }` 31 | 32 | ## Legend 33 | 34 | - improve legend icons (e.g. adopt markers, gradients, etc) 35 | - generalize legend rendering for plots and subplots 36 | - add draggable scroll bar if users need it 37 | 38 | ## Tools / Misc. 39 | 40 | - add `IsPlotChanging` to detect change in limits 41 | - add ability to extend plot/axis context menus 42 | - add LTTB downsampling for lines 43 | - add box selection to axes 44 | - first frame render delay might fix "fit pop" effect 45 | - move some code to new `implot_tools.cpp` 46 | - ColormapSlider (see metrics) 47 | - FillAlpha should not affect markers? 48 | - fix mouse text for time axes 49 | 50 | ## Optimizations 51 | 52 | - find faster way to buffer data into ImDrawList (very slow) 53 | - reduce number of calls to `PushClipRect` 54 | - explore SIMD operations for high density plot items 55 | 56 | ## Plotter Pipeline 57 | 58 | Ideally every `PlotX` function should use our faster rendering pipeline when it is applicable. 59 | 60 | ` User Data > Getter > Fitter > Renderer > RenderPrimitives` 61 | 62 | |Plotter|Getter|Fitter|Renderer|RenderPrimitives| 63 | |---|:-:|:-:|:-:|:-:| 64 | |PlotLine|Yes|Yes|Yes|Yes| 65 | |PlotScatter|Yes|Yes|Yes|Yes| 66 | |PlotStairs|Yes|Yes|Yes|Yes| 67 | |PlotShaded|Yes|Yes|Yes|Yes| 68 | |PlotBars|Yes|Yes|Yes|Yes| 69 | |PlotBarGroups|:|:|:|:| 70 | |PlotHistogram|:|:|:|:| 71 | |PlotErrorBars|Yes|Yes|No|No| 72 | |PlotStems|Yes|Yes|Yes|Yes| 73 | |PlotInfLines|Yes|Yes|Yes|Yes| 74 | |PlotPieChart|No|No|No|No| 75 | |PlotHeatmap|Yes|No|Yes|Mixed| 76 | |PlotHistogram2D|:|:|:|:| 77 | |PlotDigital|Yes|No|No|No| 78 | |PlotImage|-|-|-|-| 79 | |PlotText|-|-|-|-| 80 | |PlotDummy|-|-|-|-| 81 | 82 | ## Completed 83 | - make BeginPlot take fewer args: 84 | - make query a tool -> `DragRect` 85 | - rework DragLine/Point to use ButtonBehavior 86 | - add support for multiple x-axes and don't limit count to 3 87 | - make axis side configurable (top/left, right/bottom) via new flag `ImPlotAxisFlags_Opposite` 88 | - add support for setting tick label strings via callback 89 | - give each axis an ID, remove ad-hoc DND solution 90 | - allow axis to be drag to opposite side (ala ImGui Table headers) 91 | - legend items can be hovered even if plot is not 92 | - fix frame delay on DragX tools 93 | - remove tag from drag line/point -> add `Tag` tool 94 | - add shortcut/legacy overloads for BeginPlot 95 | - `SetupAxisConstraints()` 96 | - `SetupAxisScale()` 97 | - add `ImPlotLineFlags`, `ImPlotBarsFlags`, etc. for each plot type 98 | - add `PlotBarGroups` wrapper that makes rendering groups of bars easier, with stacked bar support 99 | - `PlotBars` restore outlines 100 | - add hover/active color for plot axes 101 | - make legend frame use ButtonBehavior 102 | - `ImPlotLegendFlags_Scroll` (default behavior) 103 | -------------------------------------------------------------------------------- /implot.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2023 Evan Pezent 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // ImPlot v0.17 24 | 25 | // Table of Contents: 26 | // 27 | // [SECTION] Macros and Defines 28 | // [SECTION] Enums and Types 29 | // [SECTION] Callbacks 30 | // [SECTION] Contexts 31 | // [SECTION] Begin/End Plot 32 | // [SECTION] Begin/End Subplot 33 | // [SECTION] Setup 34 | // [SECTION] SetNext 35 | // [SECTION] Plot Items 36 | // [SECTION] Plot Tools 37 | // [SECTION] Plot Utils 38 | // [SECTION] Legend Utils 39 | // [SECTION] Drag and Drop 40 | // [SECTION] Styling 41 | // [SECTION] Colormaps 42 | // [SECTION] Input Mapping 43 | // [SECTION] Miscellaneous 44 | // [SECTION] Demo 45 | // [SECTION] Obsolete API 46 | 47 | #pragma once 48 | #include "imgui.h" 49 | 50 | //----------------------------------------------------------------------------- 51 | // [SECTION] Macros and Defines 52 | //----------------------------------------------------------------------------- 53 | 54 | // Define attributes of all API symbols declarations (e.g. for DLL under Windows) 55 | // Using ImPlot via a shared library is not recommended, because we don't guarantee 56 | // backward nor forward ABI compatibility and also function call overhead. If you 57 | // do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellanous section). 58 | #ifndef IMPLOT_API 59 | #define IMPLOT_API 60 | #endif 61 | 62 | // ImPlot version string. 63 | #define IMPLOT_VERSION "0.17" 64 | // Indicates variable should deduced automatically. 65 | #define IMPLOT_AUTO -1 66 | // Special color used to indicate that a color should be deduced automatically. 67 | #define IMPLOT_AUTO_COL ImVec4(0,0,0,-1) 68 | // Macro for templated plotting functions; keeps header clean. 69 | #define IMPLOT_TMP template IMPLOT_API 70 | 71 | //----------------------------------------------------------------------------- 72 | // [SECTION] Enums and Types 73 | //----------------------------------------------------------------------------- 74 | 75 | // Forward declarations 76 | struct ImPlotContext; // ImPlot context (opaque struct, see implot_internal.h) 77 | 78 | // Enums/Flags 79 | typedef int ImAxis; // -> enum ImAxis_ 80 | typedef int ImPlotFlags; // -> enum ImPlotFlags_ 81 | typedef int ImPlotAxisFlags; // -> enum ImPlotAxisFlags_ 82 | typedef int ImPlotSubplotFlags; // -> enum ImPlotSubplotFlags_ 83 | typedef int ImPlotLegendFlags; // -> enum ImPlotLegendFlags_ 84 | typedef int ImPlotMouseTextFlags; // -> enum ImPlotMouseTextFlags_ 85 | typedef int ImPlotDragToolFlags; // -> ImPlotDragToolFlags_ 86 | typedef int ImPlotColormapScaleFlags; // -> ImPlotColormapScaleFlags_ 87 | 88 | typedef int ImPlotItemFlags; // -> ImPlotItemFlags_ 89 | typedef int ImPlotLineFlags; // -> ImPlotLineFlags_ 90 | typedef int ImPlotScatterFlags; // -> ImPlotScatterFlags 91 | typedef int ImPlotStairsFlags; // -> ImPlotStairsFlags_ 92 | typedef int ImPlotShadedFlags; // -> ImPlotShadedFlags_ 93 | typedef int ImPlotBarsFlags; // -> ImPlotBarsFlags_ 94 | typedef int ImPlotBarGroupsFlags; // -> ImPlotBarGroupsFlags_ 95 | typedef int ImPlotErrorBarsFlags; // -> ImPlotErrorBarsFlags_ 96 | typedef int ImPlotStemsFlags; // -> ImPlotStemsFlags_ 97 | typedef int ImPlotInfLinesFlags; // -> ImPlotInfLinesFlags_ 98 | typedef int ImPlotPieChartFlags; // -> ImPlotPieChartFlags_ 99 | typedef int ImPlotHeatmapFlags; // -> ImPlotHeatmapFlags_ 100 | typedef int ImPlotHistogramFlags; // -> ImPlotHistogramFlags_ 101 | typedef int ImPlotDigitalFlags; // -> ImPlotDigitalFlags_ 102 | typedef int ImPlotImageFlags; // -> ImPlotImageFlags_ 103 | typedef int ImPlotTextFlags; // -> ImPlotTextFlags_ 104 | typedef int ImPlotDummyFlags; // -> ImPlotDummyFlags_ 105 | 106 | typedef int ImPlotCond; // -> enum ImPlotCond_ 107 | typedef int ImPlotCol; // -> enum ImPlotCol_ 108 | typedef int ImPlotStyleVar; // -> enum ImPlotStyleVar_ 109 | typedef int ImPlotScale; // -> enum ImPlotScale_ 110 | typedef int ImPlotMarker; // -> enum ImPlotMarker_ 111 | typedef int ImPlotColormap; // -> enum ImPlotColormap_ 112 | typedef int ImPlotLocation; // -> enum ImPlotLocation_ 113 | typedef int ImPlotBin; // -> enum ImPlotBin_ 114 | 115 | // Axis indices. The values assigned may change; NEVER hardcode these. 116 | enum ImAxis_ { 117 | // horizontal axes 118 | ImAxis_X1 = 0, // enabled by default 119 | ImAxis_X2, // disabled by default 120 | ImAxis_X3, // disabled by default 121 | // vertical axes 122 | ImAxis_Y1, // enabled by default 123 | ImAxis_Y2, // disabled by default 124 | ImAxis_Y3, // disabled by default 125 | // bookeeping 126 | ImAxis_COUNT 127 | }; 128 | 129 | // Options for plots (see BeginPlot). 130 | enum ImPlotFlags_ { 131 | ImPlotFlags_None = 0, // default 132 | ImPlotFlags_NoTitle = 1 << 0, // the plot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. "##MyPlot") 133 | ImPlotFlags_NoLegend = 1 << 1, // the legend will not be displayed 134 | ImPlotFlags_NoMouseText = 1 << 2, // the mouse position, in plot coordinates, will not be displayed inside of the plot 135 | ImPlotFlags_NoInputs = 1 << 3, // the user will not be able to interact with the plot 136 | ImPlotFlags_NoMenus = 1 << 4, // the user will not be able to open context menus 137 | ImPlotFlags_NoBoxSelect = 1 << 5, // the user will not be able to box-select 138 | ImPlotFlags_NoFrame = 1 << 6, // the ImGui frame will not be rendered 139 | ImPlotFlags_Equal = 1 << 7, // x and y axes pairs will be constrained to have the same units/pixel 140 | ImPlotFlags_Crosshairs = 1 << 8, // the default mouse cursor will be replaced with a crosshair when hovered 141 | ImPlotFlags_CanvasOnly = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText 142 | }; 143 | 144 | // Options for plot axes (see SetupAxis). 145 | enum ImPlotAxisFlags_ { 146 | ImPlotAxisFlags_None = 0, // default 147 | ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is nullptr) 148 | ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed 149 | ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed 150 | ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed 151 | ImPlotAxisFlags_NoInitialFit = 1 << 4, // axis will not be initially fit to data extents on the first rendered frame 152 | ImPlotAxisFlags_NoMenus = 1 << 5, // the user will not be able to open context menus with right-click 153 | ImPlotAxisFlags_NoSideSwitch = 1 << 6, // the user will not be able to switch the axis side by dragging it 154 | ImPlotAxisFlags_NoHighlight = 1 << 7, // the axis will not have its background highlighted when hovered or held 155 | ImPlotAxisFlags_Opposite = 1 << 8, // axis ticks and labels will be rendered on the conventionally opposite side (i.e, right or top) 156 | ImPlotAxisFlags_Foreground = 1 << 9, // grid lines will be displayed in the foreground (i.e. on top of data) instead of the background 157 | ImPlotAxisFlags_Invert = 1 << 10, // the axis will be inverted 158 | ImPlotAxisFlags_AutoFit = 1 << 11, // axis will be auto-fitting to data extents 159 | ImPlotAxisFlags_RangeFit = 1 << 12, // axis will only fit points if the point is in the visible range of the **orthogonal** axis 160 | ImPlotAxisFlags_PanStretch = 1 << 13, // panning in a locked or constrained state will cause the axis to stretch if possible 161 | ImPlotAxisFlags_LockMin = 1 << 14, // the axis minimum value will be locked when panning/zooming 162 | ImPlotAxisFlags_LockMax = 1 << 15, // the axis maximum value will be locked when panning/zooming 163 | ImPlotAxisFlags_Lock = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax, 164 | ImPlotAxisFlags_NoDecorations = ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks | ImPlotAxisFlags_NoTickLabels, 165 | ImPlotAxisFlags_AuxDefault = ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_Opposite 166 | }; 167 | 168 | // Options for subplots (see BeginSubplot) 169 | enum ImPlotSubplotFlags_ { 170 | ImPlotSubplotFlags_None = 0, // default 171 | ImPlotSubplotFlags_NoTitle = 1 << 0, // the subplot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. "##MySubplot") 172 | ImPlotSubplotFlags_NoLegend = 1 << 1, // the legend will not be displayed (only applicable if ImPlotSubplotFlags_ShareItems is enabled) 173 | ImPlotSubplotFlags_NoMenus = 1 << 2, // the user will not be able to open context menus with right-click 174 | ImPlotSubplotFlags_NoResize = 1 << 3, // resize splitters between subplot cells will be not be provided 175 | ImPlotSubplotFlags_NoAlign = 1 << 4, // subplot edges will not be aligned vertically or horizontally 176 | ImPlotSubplotFlags_ShareItems = 1 << 5, // items across all subplots will be shared and rendered into a single legend entry 177 | ImPlotSubplotFlags_LinkRows = 1 << 6, // link the y-axis limits of all plots in each row (does not apply to auxiliary axes) 178 | ImPlotSubplotFlags_LinkCols = 1 << 7, // link the x-axis limits of all plots in each column (does not apply to auxiliary axes) 179 | ImPlotSubplotFlags_LinkAllX = 1 << 8, // link the x-axis limits in every plot in the subplot (does not apply to auxiliary axes) 180 | ImPlotSubplotFlags_LinkAllY = 1 << 9, // link the y-axis limits in every plot in the subplot (does not apply to auxiliary axes) 181 | ImPlotSubplotFlags_ColMajor = 1 << 10 // subplots are added in column major order instead of the default row major order 182 | }; 183 | 184 | // Options for legends (see SetupLegend) 185 | enum ImPlotLegendFlags_ { 186 | ImPlotLegendFlags_None = 0, // default 187 | ImPlotLegendFlags_NoButtons = 1 << 0, // legend icons will not function as hide/show buttons 188 | ImPlotLegendFlags_NoHighlightItem = 1 << 1, // plot items will not be highlighted when their legend entry is hovered 189 | ImPlotLegendFlags_NoHighlightAxis = 1 << 2, // axes will not be highlighted when legend entries are hovered (only relevant if x/y-axis count > 1) 190 | ImPlotLegendFlags_NoMenus = 1 << 3, // the user will not be able to open context menus with right-click 191 | ImPlotLegendFlags_Outside = 1 << 4, // legend will be rendered outside of the plot area 192 | ImPlotLegendFlags_Horizontal = 1 << 5, // legend entries will be displayed horizontally 193 | ImPlotLegendFlags_Sort = 1 << 6, // legend entries will be displayed in alphabetical order 194 | }; 195 | 196 | // Options for mouse hover text (see SetupMouseText) 197 | enum ImPlotMouseTextFlags_ { 198 | ImPlotMouseTextFlags_None = 0, // default 199 | ImPlotMouseTextFlags_NoAuxAxes = 1 << 0, // only show the mouse position for primary axes 200 | ImPlotMouseTextFlags_NoFormat = 1 << 1, // axes label formatters won't be used to render text 201 | ImPlotMouseTextFlags_ShowAlways = 1 << 2, // always display mouse position even if plot not hovered 202 | }; 203 | 204 | // Options for DragPoint, DragLine, DragRect 205 | enum ImPlotDragToolFlags_ { 206 | ImPlotDragToolFlags_None = 0, // default 207 | ImPlotDragToolFlags_NoCursors = 1 << 0, // drag tools won't change cursor icons when hovered or held 208 | ImPlotDragToolFlags_NoFit = 1 << 1, // the drag tool won't be considered for plot fits 209 | ImPlotDragToolFlags_NoInputs = 1 << 2, // lock the tool from user inputs 210 | ImPlotDragToolFlags_Delayed = 1 << 3, // tool rendering will be delayed one frame; useful when applying position-constraints 211 | }; 212 | 213 | // Flags for ColormapScale 214 | enum ImPlotColormapScaleFlags_ { 215 | ImPlotColormapScaleFlags_None = 0, // default 216 | ImPlotColormapScaleFlags_NoLabel = 1 << 0, // the colormap axis label will not be displayed 217 | ImPlotColormapScaleFlags_Opposite = 1 << 1, // render the colormap label and tick labels on the opposite side 218 | ImPlotColormapScaleFlags_Invert = 1 << 2, // invert the colormap bar and axis scale (this only affects rendering; if you only want to reverse the scale mapping, make scale_min > scale_max) 219 | }; 220 | 221 | // Flags for ANY PlotX function 222 | enum ImPlotItemFlags_ { 223 | ImPlotItemFlags_None = 0, 224 | ImPlotItemFlags_NoLegend = 1 << 0, // the item won't have a legend entry displayed 225 | ImPlotItemFlags_NoFit = 1 << 1, // the item won't be considered for plot fits 226 | }; 227 | 228 | // Flags for PlotLine 229 | enum ImPlotLineFlags_ { 230 | ImPlotLineFlags_None = 0, // default 231 | ImPlotLineFlags_Segments = 1 << 10, // a line segment will be rendered from every two consecutive points 232 | ImPlotLineFlags_Loop = 1 << 11, // the last and first point will be connected to form a closed loop 233 | ImPlotLineFlags_SkipNaN = 1 << 12, // NaNs values will be skipped instead of rendered as missing data 234 | ImPlotLineFlags_NoClip = 1 << 13, // markers (if displayed) on the edge of a plot will not be clipped 235 | ImPlotLineFlags_Shaded = 1 << 14, // a filled region between the line and horizontal origin will be rendered; use PlotShaded for more advanced cases 236 | }; 237 | 238 | // Flags for PlotScatter 239 | enum ImPlotScatterFlags_ { 240 | ImPlotScatterFlags_None = 0, // default 241 | ImPlotScatterFlags_NoClip = 1 << 10, // markers on the edge of a plot will not be clipped 242 | }; 243 | 244 | // Flags for PlotStairs 245 | enum ImPlotStairsFlags_ { 246 | ImPlotStairsFlags_None = 0, // default 247 | ImPlotStairsFlags_PreStep = 1 << 10, // the y value is continued constantly to the left from every x position, i.e. the interval (x[i-1], x[i]] has the value y[i] 248 | ImPlotStairsFlags_Shaded = 1 << 11 // a filled region between the stairs and horizontal origin will be rendered; use PlotShaded for more advanced cases 249 | }; 250 | 251 | // Flags for PlotShaded (placeholder) 252 | enum ImPlotShadedFlags_ { 253 | ImPlotShadedFlags_None = 0 // default 254 | }; 255 | 256 | // Flags for PlotBars 257 | enum ImPlotBarsFlags_ { 258 | ImPlotBarsFlags_None = 0, // default 259 | ImPlotBarsFlags_Horizontal = 1 << 10, // bars will be rendered horizontally on the current y-axis 260 | }; 261 | 262 | // Flags for PlotBarGroups 263 | enum ImPlotBarGroupsFlags_ { 264 | ImPlotBarGroupsFlags_None = 0, // default 265 | ImPlotBarGroupsFlags_Horizontal = 1 << 10, // bar groups will be rendered horizontally on the current y-axis 266 | ImPlotBarGroupsFlags_Stacked = 1 << 11, // items in a group will be stacked on top of each other 267 | }; 268 | 269 | // Flags for PlotErrorBars 270 | enum ImPlotErrorBarsFlags_ { 271 | ImPlotErrorBarsFlags_None = 0, // default 272 | ImPlotErrorBarsFlags_Horizontal = 1 << 10, // error bars will be rendered horizontally on the current y-axis 273 | }; 274 | 275 | // Flags for PlotStems 276 | enum ImPlotStemsFlags_ { 277 | ImPlotStemsFlags_None = 0, // default 278 | ImPlotStemsFlags_Horizontal = 1 << 10, // stems will be rendered horizontally on the current y-axis 279 | }; 280 | 281 | // Flags for PlotInfLines 282 | enum ImPlotInfLinesFlags_ { 283 | ImPlotInfLinesFlags_None = 0, // default 284 | ImPlotInfLinesFlags_Horizontal = 1 << 10 // lines will be rendered horizontally on the current y-axis 285 | }; 286 | 287 | // Flags for PlotPieChart 288 | enum ImPlotPieChartFlags_ { 289 | ImPlotPieChartFlags_None = 0, // default 290 | ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0) 291 | ImPlotPieChartFlags_IgnoreHidden = 1 << 11 // ignore hidden slices when drawing the pie chart (as if they were not there) 292 | }; 293 | 294 | // Flags for PlotHeatmap 295 | enum ImPlotHeatmapFlags_ { 296 | ImPlotHeatmapFlags_None = 0, // default 297 | ImPlotHeatmapFlags_ColMajor = 1 << 10, // data will be read in column major order 298 | }; 299 | 300 | // Flags for PlotHistogram and PlotHistogram2D 301 | enum ImPlotHistogramFlags_ { 302 | ImPlotHistogramFlags_None = 0, // default 303 | ImPlotHistogramFlags_Horizontal = 1 << 10, // histogram bars will be rendered horizontally (not supported by PlotHistogram2D) 304 | ImPlotHistogramFlags_Cumulative = 1 << 11, // each bin will contain its count plus the counts of all previous bins (not supported by PlotHistogram2D) 305 | ImPlotHistogramFlags_Density = 1 << 12, // counts will be normalized, i.e. the PDF will be visualized, or the CDF will be visualized if Cumulative is also set 306 | ImPlotHistogramFlags_NoOutliers = 1 << 13, // exclude values outside the specifed histogram range from the count toward normalizing and cumulative counts 307 | ImPlotHistogramFlags_ColMajor = 1 << 14 // data will be read in column major order (not supported by PlotHistogram) 308 | }; 309 | 310 | // Flags for PlotDigital (placeholder) 311 | enum ImPlotDigitalFlags_ { 312 | ImPlotDigitalFlags_None = 0 // default 313 | }; 314 | 315 | // Flags for PlotImage (placeholder) 316 | enum ImPlotImageFlags_ { 317 | ImPlotImageFlags_None = 0 // default 318 | }; 319 | 320 | // Flags for PlotText 321 | enum ImPlotTextFlags_ { 322 | ImPlotTextFlags_None = 0, // default 323 | ImPlotTextFlags_Vertical = 1 << 10 // text will be rendered vertically 324 | }; 325 | 326 | // Flags for PlotDummy (placeholder) 327 | enum ImPlotDummyFlags_ { 328 | ImPlotDummyFlags_None = 0 // default 329 | }; 330 | 331 | // Represents a condition for SetupAxisLimits etc. (same as ImGuiCond, but we only support a subset of those enums) 332 | enum ImPlotCond_ 333 | { 334 | ImPlotCond_None = ImGuiCond_None, // No condition (always set the variable), same as _Always 335 | ImPlotCond_Always = ImGuiCond_Always, // No condition (always set the variable) 336 | ImPlotCond_Once = ImGuiCond_Once, // Set the variable once per runtime session (only the first call will succeed) 337 | }; 338 | 339 | // Plot styling colors. 340 | enum ImPlotCol_ { 341 | // item styling colors 342 | ImPlotCol_Line, // plot line/outline color (defaults to next unused color in current colormap) 343 | ImPlotCol_Fill, // plot fill color for bars (defaults to the current line color) 344 | ImPlotCol_MarkerOutline, // marker outline color (defaults to the current line color) 345 | ImPlotCol_MarkerFill, // marker fill color (defaults to the current line color) 346 | ImPlotCol_ErrorBar, // error bar color (defaults to ImGuiCol_Text) 347 | // plot styling colors 348 | ImPlotCol_FrameBg, // plot frame background color (defaults to ImGuiCol_FrameBg) 349 | ImPlotCol_PlotBg, // plot area background color (defaults to ImGuiCol_WindowBg) 350 | ImPlotCol_PlotBorder, // plot area border color (defaults to ImGuiCol_Border) 351 | ImPlotCol_LegendBg, // legend background color (defaults to ImGuiCol_PopupBg) 352 | ImPlotCol_LegendBorder, // legend border color (defaults to ImPlotCol_PlotBorder) 353 | ImPlotCol_LegendText, // legend text color (defaults to ImPlotCol_InlayText) 354 | ImPlotCol_TitleText, // plot title text color (defaults to ImGuiCol_Text) 355 | ImPlotCol_InlayText, // color of text appearing inside of plots (defaults to ImGuiCol_Text) 356 | ImPlotCol_AxisText, // axis label and tick lables color (defaults to ImGuiCol_Text) 357 | ImPlotCol_AxisGrid, // axis grid color (defaults to 25% ImPlotCol_AxisText) 358 | ImPlotCol_AxisTick, // axis tick color (defaults to AxisGrid) 359 | ImPlotCol_AxisBg, // background color of axis hover region (defaults to transparent) 360 | ImPlotCol_AxisBgHovered, // axis hover color (defaults to ImGuiCol_ButtonHovered) 361 | ImPlotCol_AxisBgActive, // axis active color (defaults to ImGuiCol_ButtonActive) 362 | ImPlotCol_Selection, // box-selection color (defaults to yellow) 363 | ImPlotCol_Crosshairs, // crosshairs color (defaults to ImPlotCol_PlotBorder) 364 | ImPlotCol_COUNT 365 | }; 366 | 367 | // Plot styling variables. 368 | enum ImPlotStyleVar_ { 369 | // item styling variables 370 | ImPlotStyleVar_LineWeight, // float, plot item line weight in pixels 371 | ImPlotStyleVar_Marker, // int, marker specification 372 | ImPlotStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") 373 | ImPlotStyleVar_MarkerWeight, // float, plot outline weight of markers in pixels 374 | ImPlotStyleVar_FillAlpha, // float, alpha modifier applied to all plot item fills 375 | ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels 376 | ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels 377 | ImPlotStyleVar_DigitalBitHeight, // float, digital channels bit height (at 1) in pixels 378 | ImPlotStyleVar_DigitalBitGap, // float, digital channels bit padding gap in pixels 379 | // plot styling variables 380 | ImPlotStyleVar_PlotBorderSize, // float, thickness of border around plot area 381 | ImPlotStyleVar_MinorAlpha, // float, alpha multiplier applied to minor axis grid lines 382 | ImPlotStyleVar_MajorTickLen, // ImVec2, major tick lengths for X and Y axes 383 | ImPlotStyleVar_MinorTickLen, // ImVec2, minor tick lengths for X and Y axes 384 | ImPlotStyleVar_MajorTickSize, // ImVec2, line thickness of major ticks 385 | ImPlotStyleVar_MinorTickSize, // ImVec2, line thickness of minor ticks 386 | ImPlotStyleVar_MajorGridSize, // ImVec2, line thickness of major grid lines 387 | ImPlotStyleVar_MinorGridSize, // ImVec2, line thickness of minor grid lines 388 | ImPlotStyleVar_PlotPadding, // ImVec2, padding between widget frame and plot area, labels, or outside legends (i.e. main padding) 389 | ImPlotStyleVar_LabelPadding, // ImVec2, padding between axes labels, tick labels, and plot edge 390 | ImPlotStyleVar_LegendPadding, // ImVec2, legend padding from plot edges 391 | ImPlotStyleVar_LegendInnerPadding, // ImVec2, legend inner padding from legend edges 392 | ImPlotStyleVar_LegendSpacing, // ImVec2, spacing between legend entries 393 | ImPlotStyleVar_MousePosPadding, // ImVec2, padding between plot edge and interior info text 394 | ImPlotStyleVar_AnnotationPadding, // ImVec2, text padding around annotation labels 395 | ImPlotStyleVar_FitPadding, // ImVec2, additional fit padding as a percentage of the fit extents (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y) 396 | ImPlotStyleVar_PlotDefaultSize, // ImVec2, default size used when ImVec2(0,0) is passed to BeginPlot 397 | ImPlotStyleVar_PlotMinSize, // ImVec2, minimum size plot frame can be when shrunk 398 | ImPlotStyleVar_COUNT 399 | }; 400 | 401 | // Axis scale 402 | enum ImPlotScale_ { 403 | ImPlotScale_Linear = 0, // default linear scale 404 | ImPlotScale_Time, // date/time scale 405 | ImPlotScale_Log10, // base 10 logartithmic scale 406 | ImPlotScale_SymLog, // symmetric log scale 407 | }; 408 | 409 | // Marker specifications. 410 | enum ImPlotMarker_ { 411 | ImPlotMarker_None = -1, // no marker 412 | ImPlotMarker_Circle, // a circle marker (default) 413 | ImPlotMarker_Square, // a square maker 414 | ImPlotMarker_Diamond, // a diamond marker 415 | ImPlotMarker_Up, // an upward-pointing triangle marker 416 | ImPlotMarker_Down, // an downward-pointing triangle marker 417 | ImPlotMarker_Left, // an leftward-pointing triangle marker 418 | ImPlotMarker_Right, // an rightward-pointing triangle marker 419 | ImPlotMarker_Cross, // a cross marker (not fillable) 420 | ImPlotMarker_Plus, // a plus marker (not fillable) 421 | ImPlotMarker_Asterisk, // a asterisk marker (not fillable) 422 | ImPlotMarker_COUNT 423 | }; 424 | 425 | // Built-in colormaps 426 | enum ImPlotColormap_ { 427 | ImPlotColormap_Deep = 0, // a.k.a. seaborn deep (qual=true, n=10) (default) 428 | ImPlotColormap_Dark = 1, // a.k.a. matplotlib "Set1" (qual=true, n=9 ) 429 | ImPlotColormap_Pastel = 2, // a.k.a. matplotlib "Pastel1" (qual=true, n=9 ) 430 | ImPlotColormap_Paired = 3, // a.k.a. matplotlib "Paired" (qual=true, n=12) 431 | ImPlotColormap_Viridis = 4, // a.k.a. matplotlib "viridis" (qual=false, n=11) 432 | ImPlotColormap_Plasma = 5, // a.k.a. matplotlib "plasma" (qual=false, n=11) 433 | ImPlotColormap_Hot = 6, // a.k.a. matplotlib/MATLAB "hot" (qual=false, n=11) 434 | ImPlotColormap_Cool = 7, // a.k.a. matplotlib/MATLAB "cool" (qual=false, n=11) 435 | ImPlotColormap_Pink = 8, // a.k.a. matplotlib/MATLAB "pink" (qual=false, n=11) 436 | ImPlotColormap_Jet = 9, // a.k.a. MATLAB "jet" (qual=false, n=11) 437 | ImPlotColormap_Twilight = 10, // a.k.a. matplotlib "twilight" (qual=false, n=11) 438 | ImPlotColormap_RdBu = 11, // red/blue, Color Brewer (qual=false, n=11) 439 | ImPlotColormap_BrBG = 12, // brown/blue-green, Color Brewer (qual=false, n=11) 440 | ImPlotColormap_PiYG = 13, // pink/yellow-green, Color Brewer (qual=false, n=11) 441 | ImPlotColormap_Spectral = 14, // color spectrum, Color Brewer (qual=false, n=11) 442 | ImPlotColormap_Greys = 15, // white/black (qual=false, n=2 ) 443 | }; 444 | 445 | // Used to position items on a plot (e.g. legends, labels, etc.) 446 | enum ImPlotLocation_ { 447 | ImPlotLocation_Center = 0, // center-center 448 | ImPlotLocation_North = 1 << 0, // top-center 449 | ImPlotLocation_South = 1 << 1, // bottom-center 450 | ImPlotLocation_West = 1 << 2, // center-left 451 | ImPlotLocation_East = 1 << 3, // center-right 452 | ImPlotLocation_NorthWest = ImPlotLocation_North | ImPlotLocation_West, // top-left 453 | ImPlotLocation_NorthEast = ImPlotLocation_North | ImPlotLocation_East, // top-right 454 | ImPlotLocation_SouthWest = ImPlotLocation_South | ImPlotLocation_West, // bottom-left 455 | ImPlotLocation_SouthEast = ImPlotLocation_South | ImPlotLocation_East // bottom-right 456 | }; 457 | 458 | // Enums for different automatic histogram binning methods (k = bin count or w = bin width) 459 | enum ImPlotBin_ { 460 | ImPlotBin_Sqrt = -1, // k = sqrt(n) 461 | ImPlotBin_Sturges = -2, // k = 1 + log2(n) 462 | ImPlotBin_Rice = -3, // k = 2 * cbrt(n) 463 | ImPlotBin_Scott = -4, // w = 3.49 * sigma / cbrt(n) 464 | }; 465 | 466 | // Double precision version of ImVec2 used by ImPlot. Extensible by end users. 467 | IM_MSVC_RUNTIME_CHECKS_OFF 468 | struct ImPlotPoint { 469 | double x, y; 470 | constexpr ImPlotPoint() : x(0.0), y(0.0) { } 471 | constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { } 472 | constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { } 473 | double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; } 474 | double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; } 475 | #ifdef IMPLOT_POINT_CLASS_EXTRA 476 | IMPLOT_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h 477 | // to convert back and forth between your math types and ImPlotPoint. 478 | #endif 479 | }; 480 | IM_MSVC_RUNTIME_CHECKS_RESTORE 481 | 482 | // Range defined by a min/max value. 483 | struct ImPlotRange { 484 | double Min, Max; 485 | constexpr ImPlotRange() : Min(0.0), Max(0.0) { } 486 | constexpr ImPlotRange(double _min, double _max) : Min(_min), Max(_max) { } 487 | bool Contains(double value) const { return value >= Min && value <= Max; } 488 | double Size() const { return Max - Min; } 489 | double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; } 490 | }; 491 | 492 | // Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max(). 493 | struct ImPlotRect { 494 | ImPlotRange X, Y; 495 | constexpr ImPlotRect() : X(0.0,0.0), Y(0.0,0.0) { } 496 | constexpr ImPlotRect(double x_min, double x_max, double y_min, double y_max) : X(x_min, x_max), Y(y_min, y_max) { } 497 | bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); } 498 | bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); } 499 | ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); } 500 | ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); } 501 | ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); } 502 | ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); } 503 | ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); } 504 | }; 505 | 506 | // Plot style structure 507 | struct ImPlotStyle { 508 | // item styling variables 509 | float LineWeight; // = 1, item line weight in pixels 510 | int Marker; // = ImPlotMarker_None, marker specification 511 | float MarkerSize; // = 4, marker size in pixels (roughly the marker's "radius") 512 | float MarkerWeight; // = 1, outline weight of markers in pixels 513 | float FillAlpha; // = 1, alpha modifier applied to plot fills 514 | float ErrorBarSize; // = 5, error bar whisker width in pixels 515 | float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels 516 | float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels 517 | float DigitalBitGap; // = 4, digital channels bit padding gap in pixels 518 | // plot styling variables 519 | float PlotBorderSize; // = 1, line thickness of border around plot area 520 | float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines 521 | ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes 522 | ImVec2 MinorTickLen; // = 5,5 minor tick lengths for X and Y axes 523 | ImVec2 MajorTickSize; // = 1,1 line thickness of major ticks 524 | ImVec2 MinorTickSize; // = 1,1 line thickness of minor ticks 525 | ImVec2 MajorGridSize; // = 1,1 line thickness of major grid lines 526 | ImVec2 MinorGridSize; // = 1,1 line thickness of minor grid lines 527 | ImVec2 PlotPadding; // = 10,10 padding between widget frame and plot area, labels, or outside legends (i.e. main padding) 528 | ImVec2 LabelPadding; // = 5,5 padding between axes labels, tick labels, and plot edge 529 | ImVec2 LegendPadding; // = 10,10 legend padding from plot edges 530 | ImVec2 LegendInnerPadding; // = 5,5 legend inner padding from legend edges 531 | ImVec2 LegendSpacing; // = 5,0 spacing between legend entries 532 | ImVec2 MousePosPadding; // = 10,10 padding between plot edge and interior mouse location text 533 | ImVec2 AnnotationPadding; // = 2,2 text padding around annotation labels 534 | ImVec2 FitPadding; // = 0,0 additional fit padding as a percentage of the fit extents (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y) 535 | ImVec2 PlotDefaultSize; // = 400,300 default size used when ImVec2(0,0) is passed to BeginPlot 536 | ImVec2 PlotMinSize; // = 200,150 minimum size plot frame can be when shrunk 537 | // style colors 538 | ImVec4 Colors[ImPlotCol_COUNT]; // Array of styling colors. Indexable with ImPlotCol_ enums. 539 | // colormap 540 | ImPlotColormap Colormap; // The current colormap. Set this to either an ImPlotColormap_ enum or an index returned by AddColormap. 541 | // settings/flags 542 | bool UseLocalTime; // = false, axis labels will be formatted for your timezone when ImPlotAxisFlag_Time is enabled 543 | bool UseISO8601; // = false, dates will be formatted according to ISO 8601 where applicable (e.g. YYYY-MM-DD, YYYY-MM, --MM-DD, etc.) 544 | bool Use24HourClock; // = false, times will be formatted using a 24 hour clock 545 | IMPLOT_API ImPlotStyle(); 546 | }; 547 | 548 | // Support for legacy versions 549 | #if (IMGUI_VERSION_NUM < 18716) // Renamed in 1.88 550 | #define ImGuiMod_None 0 551 | #define ImGuiMod_Ctrl ImGuiKeyModFlags_Ctrl 552 | #define ImGuiMod_Shift ImGuiKeyModFlags_Shift 553 | #define ImGuiMod_Alt ImGuiKeyModFlags_Alt 554 | #define ImGuiMod_Super ImGuiKeyModFlags_Super 555 | #elif (IMGUI_VERSION_NUM < 18823) // Renamed in 1.89, sorry 556 | #define ImGuiMod_None 0 557 | #define ImGuiMod_Ctrl ImGuiModFlags_Ctrl 558 | #define ImGuiMod_Shift ImGuiModFlags_Shift 559 | #define ImGuiMod_Alt ImGuiModFlags_Alt 560 | #define ImGuiMod_Super ImGuiModFlags_Super 561 | #endif 562 | 563 | // Input mapping structure. Default values listed. See also MapInputDefault, MapInputReverse. 564 | struct ImPlotInputMap { 565 | ImGuiMouseButton Pan; // LMB enables panning when held, 566 | int PanMod; // none optional modifier that must be held for panning/fitting 567 | ImGuiMouseButton Fit; // LMB initiates fit when double clicked 568 | ImGuiMouseButton Select; // RMB begins box selection when pressed and confirms selection when released 569 | ImGuiMouseButton SelectCancel; // LMB cancels active box selection when pressed; cannot be same as Select 570 | int SelectMod; // none optional modifier that must be held for box selection 571 | int SelectHorzMod; // Alt expands active box selection horizontally to plot edge when held 572 | int SelectVertMod; // Shift expands active box selection vertically to plot edge when held 573 | ImGuiMouseButton Menu; // RMB opens context menus (if enabled) when clicked 574 | int OverrideMod; // Ctrl when held, all input is ignored; used to enable axis/plots as DND sources 575 | int ZoomMod; // none optional modifier that must be held for scroll wheel zooming 576 | float ZoomRate; // 0.1f zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click); make negative to invert 577 | IMPLOT_API ImPlotInputMap(); 578 | }; 579 | 580 | //----------------------------------------------------------------------------- 581 | // [SECTION] Callbacks 582 | //----------------------------------------------------------------------------- 583 | 584 | // Callback signature for axis tick label formatter. 585 | typedef int (*ImPlotFormatter)(double value, char* buff, int size, void* user_data); 586 | 587 | // Callback signature for data getter. 588 | typedef ImPlotPoint (*ImPlotGetter)(int idx, void* user_data); 589 | 590 | // Callback signature for axis transform. 591 | typedef double (*ImPlotTransform)(double value, void* user_data); 592 | 593 | namespace ImPlot { 594 | 595 | //----------------------------------------------------------------------------- 596 | // [SECTION] Contexts 597 | //----------------------------------------------------------------------------- 598 | 599 | // Creates a new ImPlot context. Call this after ImGui::CreateContext. 600 | IMPLOT_API ImPlotContext* CreateContext(); 601 | // Destroys an ImPlot context. Call this before ImGui::DestroyContext. nullptr = destroy current context. 602 | IMPLOT_API void DestroyContext(ImPlotContext* ctx = nullptr); 603 | // Returns the current ImPlot context. nullptr if no context has ben set. 604 | IMPLOT_API ImPlotContext* GetCurrentContext(); 605 | // Sets the current ImPlot context. 606 | IMPLOT_API void SetCurrentContext(ImPlotContext* ctx); 607 | 608 | // Sets the current **ImGui** context. This is ONLY necessary if you are compiling 609 | // ImPlot as a DLL (not recommended) separate from your ImGui compilation. It 610 | // sets the global variable GImGui, which is not shared across DLL boundaries. 611 | // See GImGui documentation in imgui.cpp for more details. 612 | IMPLOT_API void SetImGuiContext(ImGuiContext* ctx); 613 | 614 | //----------------------------------------------------------------------------- 615 | // [SECTION] Begin/End Plot 616 | //----------------------------------------------------------------------------- 617 | 618 | // Starts a 2D plotting context. If this function returns true, EndPlot() MUST 619 | // be called! You are encouraged to use the following convention: 620 | // 621 | // if (BeginPlot(...)) { 622 | // PlotLine(...); 623 | // ... 624 | // EndPlot(); 625 | // } 626 | // 627 | // Important notes: 628 | // 629 | // - #title_id must be unique to the current ImGui ID scope. If you need to avoid ID 630 | // collisions or don't want to display a title in the plot, use double hashes 631 | // (e.g. "MyPlot##HiddenIdText" or "##NoTitle"). 632 | // - #size is the **frame** size of the plot widget, not the plot area. The default 633 | // size of plots (i.e. when ImVec2(0,0)) can be modified in your ImPlotStyle. 634 | IMPLOT_API bool BeginPlot(const char* title_id, const ImVec2& size=ImVec2(-1,0), ImPlotFlags flags=0); 635 | 636 | // Only call EndPlot() if BeginPlot() returns true! Typically called at the end 637 | // of an if statement conditioned on BeginPlot(). See example above. 638 | IMPLOT_API void EndPlot(); 639 | 640 | //----------------------------------------------------------------------------- 641 | // [SECTION] Begin/End Subplots 642 | //----------------------------------------------------------------------------- 643 | 644 | // Starts a subdivided plotting context. If the function returns true, 645 | // EndSubplots() MUST be called! Call BeginPlot/EndPlot AT MOST [rows*cols] 646 | // times in between the begining and end of the subplot context. Plots are 647 | // added in row major order. 648 | // 649 | // Example: 650 | // 651 | // if (BeginSubplots("My Subplot",2,3,ImVec2(800,400)) { 652 | // for (int i = 0; i < 6; ++i) { 653 | // if (BeginPlot(...)) { 654 | // ImPlot::PlotLine(...); 655 | // ... 656 | // EndPlot(); 657 | // } 658 | // } 659 | // EndSubplots(); 660 | // } 661 | // 662 | // Produces: 663 | // 664 | // [0] | [1] | [2] 665 | // ----|-----|---- 666 | // [3] | [4] | [5] 667 | // 668 | // Important notes: 669 | // 670 | // - #title_id must be unique to the current ImGui ID scope. If you need to avoid ID 671 | // collisions or don't want to display a title in the plot, use double hashes 672 | // (e.g. "MySubplot##HiddenIdText" or "##NoTitle"). 673 | // - #rows and #cols must be greater than 0. 674 | // - #size is the size of the entire grid of subplots, not the individual plots 675 | // - #row_ratios and #col_ratios must have AT LEAST #rows and #cols elements, 676 | // respectively. These are the sizes of the rows and columns expressed in ratios. 677 | // If the user adjusts the dimensions, the arrays are updated with new ratios. 678 | // 679 | // Important notes regarding BeginPlot from inside of BeginSubplots: 680 | // 681 | // - The #title_id parameter of _BeginPlot_ (see above) does NOT have to be 682 | // unique when called inside of a subplot context. Subplot IDs are hashed 683 | // for your convenience so you don't have call PushID or generate unique title 684 | // strings. Simply pass an empty string to BeginPlot unless you want to title 685 | // each subplot. 686 | // - The #size parameter of _BeginPlot_ (see above) is ignored when inside of a 687 | // subplot context. The actual size of the subplot will be based on the 688 | // #size value you pass to _BeginSubplots_ and #row/#col_ratios if provided. 689 | 690 | IMPLOT_API bool BeginSubplots(const char* title_id, 691 | int rows, 692 | int cols, 693 | const ImVec2& size, 694 | ImPlotSubplotFlags flags = 0, 695 | float* row_ratios = nullptr, 696 | float* col_ratios = nullptr); 697 | 698 | // Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end 699 | // of an if statement conditioned on BeginSublots(). See example above. 700 | IMPLOT_API void EndSubplots(); 701 | 702 | //----------------------------------------------------------------------------- 703 | // [SECTION] Setup 704 | //----------------------------------------------------------------------------- 705 | 706 | // The following API allows you to setup and customize various aspects of the 707 | // current plot. The functions should be called immediately after BeginPlot 708 | // and before any other API calls. Typical usage is as follows: 709 | 710 | // if (BeginPlot(...)) { 1) begin a new plot 711 | // SetupAxis(ImAxis_X1, "My X-Axis"); 2) make Setup calls 712 | // SetupAxis(ImAxis_Y1, "My Y-Axis"); 713 | // SetupLegend(ImPlotLocation_North); 714 | // ... 715 | // SetupFinish(); 3) [optional] explicitly finish setup 716 | // PlotLine(...); 4) plot items 717 | // ... 718 | // EndPlot(); 5) end the plot 719 | // } 720 | // 721 | // Important notes: 722 | // 723 | // - Always call Setup code at the top of your BeginPlot conditional statement. 724 | // - Setup is locked once you start plotting or explicitly call SetupFinish. 725 | // Do NOT call Setup code after you begin plotting or after you make 726 | // any non-Setup API calls (e.g. utils like PlotToPixels also lock Setup) 727 | // - Calling SetupFinish is OPTIONAL, but probably good practice. If you do not 728 | // call it yourself, then the first subsequent plotting or utility function will 729 | // call it for you. 730 | 731 | // Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label. 732 | IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0); 733 | // Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. Inversion with v_min > v_max is not supported; use SetupAxisLimits instead. 734 | IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); 735 | // Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot. 736 | IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max); 737 | // Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f). 738 | IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt); 739 | // Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data. 740 | IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=nullptr); 741 | // Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true. 742 | IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false); 743 | // Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true. 744 | IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false); 745 | // Sets an axis' scale using built-in options. 746 | IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale); 747 | // Sets an axis' scale using user supplied forward and inverse transfroms. 748 | IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr); 749 | // Sets an axis' limits constraints. 750 | IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max); 751 | // Sets an axis' zoom constraints. 752 | IMPLOT_API void SetupAxisZoomConstraints(ImAxis axis, double z_min, double z_max); 753 | 754 | // Sets the label and/or flags for primary X and Y axes (shorthand for two calls to SetupAxis). 755 | IMPLOT_API void SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFlags x_flags=0, ImPlotAxisFlags y_flags=0); 756 | // Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits). 757 | IMPLOT_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once); 758 | 759 | // Sets up the plot legend. This can also be called immediately after BeginSubplots when using ImPlotSubplotFlags_ShareItems. 760 | IMPLOT_API void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags=0); 761 | // Set the location of the current plot's mouse position text (default = South|East). 762 | IMPLOT_API void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags=0); 763 | 764 | // Explicitly finalize plot setup. Once you call this, you cannot make anymore Setup calls for the current plot! 765 | // Note that calling this function is OPTIONAL; it will be called by the first subsequent setup-locking API call. 766 | IMPLOT_API void SetupFinish(); 767 | 768 | //----------------------------------------------------------------------------- 769 | // [SECTION] SetNext 770 | //----------------------------------------------------------------------------- 771 | 772 | // Though you should default to the `Setup` API above, there are some scenarios 773 | // where (re)configuring a plot or axis before `BeginPlot` is needed (e.g. if 774 | // using a preceding button or slider widget to change the plot limits). In 775 | // this case, you can use the `SetNext` API below. While this is not as feature 776 | // rich as the Setup API, most common needs are provided. These functions can be 777 | // called anwhere except for inside of `Begin/EndPlot`. For example: 778 | 779 | // if (ImGui::Button("Center Plot")) 780 | // ImPlot::SetNextPlotLimits(-1,1,-1,1); 781 | // if (ImPlot::BeginPlot(...)) { 782 | // ... 783 | // ImPlot::EndPlot(); 784 | // } 785 | // 786 | // Important notes: 787 | // 788 | // - You must still enable non-default axes with SetupAxis for these functions 789 | // to work properly. 790 | 791 | // Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. 792 | IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); 793 | // Links an upcoming axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot! 794 | IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max); 795 | // Set an upcoming axis to auto fit to its data. 796 | IMPLOT_API void SetNextAxisToFit(ImAxis axis); 797 | 798 | // Sets the upcoming primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits). 799 | IMPLOT_API void SetNextAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once); 800 | // Sets all upcoming axes to auto fit to their data. 801 | IMPLOT_API void SetNextAxesToFit(); 802 | 803 | //----------------------------------------------------------------------------- 804 | // [SECTION] Plot Items 805 | //----------------------------------------------------------------------------- 806 | 807 | // The main plotting API is provied below. Call these functions between 808 | // Begin/EndPlot and after any Setup API calls. Each plots data on the current 809 | // x and y axes, which can be changed with `SetAxis/Axes`. 810 | // 811 | // The templated functions are explicitly instantiated in implot_items.cpp. 812 | // They are not intended to be used generically with custom types. You will get 813 | // a linker error if you try! All functions support the following scalar types: 814 | // 815 | // float, double, ImS8, ImU8, ImS16, ImU16, ImS32, ImU32, ImS64, ImU64 816 | // 817 | // 818 | // If you need to plot custom or non-homogenous data you have a few options: 819 | // 820 | // 1. If your data is a simple struct/class (e.g. Vector2f), you can use striding. 821 | // This is the most performant option if applicable. 822 | // 823 | // struct Vector2f { float X, Y; }; 824 | // ... 825 | // Vector2f data[42]; 826 | // ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, 0, sizeof(Vector2f)); 827 | // 828 | // 2. Write a custom getter C function or C++ lambda and pass it and optionally your data to 829 | // an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a slight performance 830 | // cost, but probably not enough to worry about unless your data is very large. Examples: 831 | // 832 | // ImPlotPoint MyDataGetter(void* data, int idx) { 833 | // MyData* my_data = (MyData*)data; 834 | // ImPlotPoint p; 835 | // p.x = my_data->GetTime(idx); 836 | // p.y = my_data->GetValue(idx); 837 | // return p 838 | // } 839 | // ... 840 | // auto my_lambda = [](int idx, void*) { 841 | // double t = idx / 999.0; 842 | // return ImPlotPoint(t, 0.5+0.5*std::sin(2*PI*10*t)); 843 | // }; 844 | // ... 845 | // if (ImPlot::BeginPlot("MyPlot")) { 846 | // MyData my_data; 847 | // ImPlot::PlotScatterG("scatter", MyDataGetter, &my_data, my_data.Size()); 848 | // ImPlot::PlotLineG("line", my_lambda, nullptr, 1000); 849 | // ImPlot::EndPlot(); 850 | // } 851 | // 852 | // NB: All types are converted to double before plotting. You may lose information 853 | // if you try plotting extremely large 64-bit integral types. Proceed with caution! 854 | 855 | // Plots a standard 2D line plot. 856 | IMPLOT_TMP void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T)); 857 | IMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T)); 858 | IMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotLineFlags flags=0); 859 | 860 | // Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle. 861 | IMPLOT_TMP void PlotScatter(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T)); 862 | IMPLOT_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T)); 863 | IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotScatterFlags flags=0); 864 | 865 | // Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i] 866 | IMPLOT_TMP void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T)); 867 | IMPLOT_TMP void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T)); 868 | IMPLOT_API void PlotStairsG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotStairsFlags flags=0); 869 | 870 | // Plots a shaded (filled) region between two lines, or a line and a horizontal reference. Set yref to +/-INFINITY for infinite fill extents. 871 | IMPLOT_TMP void PlotShaded(const char* label_id, const T* values, int count, double yref=0, double xscale=1, double xstart=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); 872 | IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double yref=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); 873 | IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); 874 | IMPLOT_API void PlotShadedG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0); 875 | 876 | // Plots a bar graph. Vertical by default. #bar_size and #shift are in plot units. 877 | IMPLOT_TMP void PlotBars(const char* label_id, const T* values, int count, double bar_size=0.67, double shift=0, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T)); 878 | IMPLOT_TMP void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T)); 879 | IMPLOT_API void PlotBarsG(const char* label_id, ImPlotGetter getter, void* data, int count, double bar_size, ImPlotBarsFlags flags=0); 880 | 881 | // Plots a group of bars. #values is a row-major matrix with #item_count rows and #group_count cols. #label_ids should have #item_count elements. 882 | IMPLOT_TMP void PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_size=0.67, double shift=0, ImPlotBarGroupsFlags flags=0); 883 | 884 | // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. 885 | IMPLOT_TMP void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags=0, int offset=0, int stride=sizeof(T)); 886 | IMPLOT_TMP void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags=0, int offset=0, int stride=sizeof(T)); 887 | 888 | // Plots stems. Vertical by default. 889 | IMPLOT_TMP void PlotStems(const char* label_id, const T* values, int count, double ref=0, double scale=1, double start=0, ImPlotStemsFlags flags=0, int offset=0, int stride=sizeof(T)); 890 | IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double ref=0, ImPlotStemsFlags flags=0, int offset=0, int stride=sizeof(T)); 891 | 892 | // Plots infinite vertical or horizontal lines (e.g. for references or asymptotes). 893 | IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T)); 894 | 895 | // Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels. 896 | IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data=nullptr, double angle0=90, ImPlotPieChartFlags flags=0); 897 | IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0); 898 | 899 | // Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels. 900 | IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0); 901 | 902 | // Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range. 903 | // Otherwise, outlier values outside of the range are not binned. The largest bin count or density is returned. 904 | IMPLOT_TMP double PlotHistogram(const char* label_id, const T* values, int count, int bins=ImPlotBin_Sturges, double bar_scale=1.0, ImPlotRange range=ImPlotRange(), ImPlotHistogramFlags flags=0); 905 | 906 | // Plots two dimensional, bivariate histogram as a heatmap. #x_bins and #y_bins can be a positive integer or an ImPlotBin. If #range is left unspecified, the min/max of 907 | // #xs an #ys will be used as the ranges. Otherwise, outlier values outside of range are not binned. The largest bin count or density is returned. 908 | IMPLOT_TMP double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins=ImPlotBin_Sturges, int y_bins=ImPlotBin_Sturges, ImPlotRect range=ImPlotRect(), ImPlotHistogramFlags flags=0); 909 | 910 | // Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot. 911 | IMPLOT_TMP void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags=0, int offset=0, int stride=sizeof(T)); 912 | IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0); 913 | 914 | // Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down). 915 | IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0); 916 | 917 | // Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...). 918 | IMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix_offset=ImVec2(0,0), ImPlotTextFlags flags=0); 919 | 920 | // Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line) 921 | IMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0); 922 | 923 | //----------------------------------------------------------------------------- 924 | // [SECTION] Plot Tools 925 | //----------------------------------------------------------------------------- 926 | 927 | // The following can be used to render interactive elements and/or annotations. 928 | // Like the item plotting functions above, they apply to the current x and y 929 | // axes, which can be changed with `SetAxis/SetAxes`. These functions return true 930 | // when user interaction causes the provided coordinates to change. Additional 931 | // user interactions can be retrieved through the optional output parameters. 932 | 933 | // Shows a draggable point at x,y. #col defaults to ImGuiCol_Text. 934 | IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); 935 | // Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text. 936 | IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); 937 | // Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text. 938 | IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); 939 | // Shows a draggable and resizeable rectangle. 940 | IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); 941 | 942 | // Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top. 943 | IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false); 944 | IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, const char* fmt, ...) IM_FMTARGS(6); 945 | IMPLOT_API void AnnotationV(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, const char* fmt, va_list args) IM_FMTLIST(6); 946 | 947 | // Shows a x-axis tag at the specified coordinate value. 948 | IMPLOT_API void TagX(double x, const ImVec4& col, bool round = false); 949 | IMPLOT_API void TagX(double x, const ImVec4& col, const char* fmt, ...) IM_FMTARGS(3); 950 | IMPLOT_API void TagXV(double x, const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(3); 951 | 952 | // Shows a y-axis tag at the specified coordinate value. 953 | IMPLOT_API void TagY(double y, const ImVec4& col, bool round = false); 954 | IMPLOT_API void TagY(double y, const ImVec4& col, const char* fmt, ...) IM_FMTARGS(3); 955 | IMPLOT_API void TagYV(double y, const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(3); 956 | 957 | //----------------------------------------------------------------------------- 958 | // [SECTION] Plot Utils 959 | //----------------------------------------------------------------------------- 960 | 961 | // Select which axis/axes will be used for subsequent plot elements. 962 | IMPLOT_API void SetAxis(ImAxis axis); 963 | IMPLOT_API void SetAxes(ImAxis x_axis, ImAxis y_axis); 964 | 965 | // Convert pixels to a position in the current plot's coordinate system. Passing IMPLOT_AUTO uses the current axes. 966 | IMPLOT_API ImPlotPoint PixelsToPlot(const ImVec2& pix, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 967 | IMPLOT_API ImPlotPoint PixelsToPlot(float x, float y, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 968 | 969 | // Convert a position in the current plot's coordinate system to pixels. Passing IMPLOT_AUTO uses the current axes. 970 | IMPLOT_API ImVec2 PlotToPixels(const ImPlotPoint& plt, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 971 | IMPLOT_API ImVec2 PlotToPixels(double x, double y, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 972 | 973 | // Get the current Plot position (top-left) in pixels. 974 | IMPLOT_API ImVec2 GetPlotPos(); 975 | // Get the curent Plot size in pixels. 976 | IMPLOT_API ImVec2 GetPlotSize(); 977 | 978 | // Returns the mouse position in x,y coordinates of the current plot. Passing IMPLOT_AUTO uses the current axes. 979 | IMPLOT_API ImPlotPoint GetPlotMousePos(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 980 | // Returns the current plot axis range. 981 | IMPLOT_API ImPlotRect GetPlotLimits(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 982 | 983 | // Returns true if the plot area in the current plot is hovered. 984 | IMPLOT_API bool IsPlotHovered(); 985 | // Returns true if the axis label area in the current plot is hovered. 986 | IMPLOT_API bool IsAxisHovered(ImAxis axis); 987 | // Returns true if the bounding frame of a subplot is hovered. 988 | IMPLOT_API bool IsSubplotsHovered(); 989 | 990 | // Returns true if the current plot is being box selected. 991 | IMPLOT_API bool IsPlotSelected(); 992 | // Returns the current plot box selection bounds. Passing IMPLOT_AUTO uses the current axes. 993 | IMPLOT_API ImPlotRect GetPlotSelection(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO); 994 | // Cancels a the current plot box selection. 995 | IMPLOT_API void CancelPlotSelection(); 996 | 997 | // Hides or shows the next plot item (i.e. as if it were toggled from the legend). 998 | // Use ImPlotCond_Always if you need to forcefully set this every frame. 999 | IMPLOT_API void HideNextItem(bool hidden = true, ImPlotCond cond = ImPlotCond_Once); 1000 | 1001 | // Use the following around calls to Begin/EndPlot to align l/r/t/b padding. 1002 | // Consider using Begin/EndSubplots first. They are more feature rich and 1003 | // accomplish the same behaviour by default. The functions below offer lower 1004 | // level control of plot alignment. 1005 | 1006 | // Align axis padding over multiple plots in a single row or column. #group_id must 1007 | // be unique. If this function returns true, EndAlignedPlots() must be called. 1008 | IMPLOT_API bool BeginAlignedPlots(const char* group_id, bool vertical = true); 1009 | // Only call EndAlignedPlots() if BeginAlignedPlots() returns true! 1010 | IMPLOT_API void EndAlignedPlots(); 1011 | 1012 | //----------------------------------------------------------------------------- 1013 | // [SECTION] Legend Utils 1014 | //----------------------------------------------------------------------------- 1015 | 1016 | // Begin a popup for a legend entry. 1017 | IMPLOT_API bool BeginLegendPopup(const char* label_id, ImGuiMouseButton mouse_button=1); 1018 | // End a popup for a legend entry. 1019 | IMPLOT_API void EndLegendPopup(); 1020 | // Returns true if a plot item legend entry is hovered. 1021 | IMPLOT_API bool IsLegendEntryHovered(const char* label_id); 1022 | 1023 | //----------------------------------------------------------------------------- 1024 | // [SECTION] Drag and Drop 1025 | //----------------------------------------------------------------------------- 1026 | 1027 | // Turns the current plot's plotting area into a drag and drop target. Don't forget to call EndDragDropTarget! 1028 | IMPLOT_API bool BeginDragDropTargetPlot(); 1029 | // Turns the current plot's X-axis into a drag and drop target. Don't forget to call EndDragDropTarget! 1030 | IMPLOT_API bool BeginDragDropTargetAxis(ImAxis axis); 1031 | // Turns the current plot's legend into a drag and drop target. Don't forget to call EndDragDropTarget! 1032 | IMPLOT_API bool BeginDragDropTargetLegend(); 1033 | // Ends a drag and drop target (currently just an alias for ImGui::EndDragDropTarget). 1034 | IMPLOT_API void EndDragDropTarget(); 1035 | 1036 | // NB: By default, plot and axes drag and drop *sources* require holding the Ctrl modifier to initiate the drag. 1037 | // You can change the modifier if desired. If ImGuiMod_None is provided, the axes will be locked from panning. 1038 | 1039 | // Turns the current plot's plotting area into a drag and drop source. You must hold Ctrl. Don't forget to call EndDragDropSource! 1040 | IMPLOT_API bool BeginDragDropSourcePlot(ImGuiDragDropFlags flags=0); 1041 | // Turns the current plot's X-axis into a drag and drop source. You must hold Ctrl. Don't forget to call EndDragDropSource! 1042 | IMPLOT_API bool BeginDragDropSourceAxis(ImAxis axis, ImGuiDragDropFlags flags=0); 1043 | // Turns an item in the current plot's legend into drag and drop source. Don't forget to call EndDragDropSource! 1044 | IMPLOT_API bool BeginDragDropSourceItem(const char* label_id, ImGuiDragDropFlags flags=0); 1045 | // Ends a drag and drop source (currently just an alias for ImGui::EndDragDropSource). 1046 | IMPLOT_API void EndDragDropSource(); 1047 | 1048 | //----------------------------------------------------------------------------- 1049 | // [SECTION] Styling 1050 | //----------------------------------------------------------------------------- 1051 | 1052 | // Styling colors in ImPlot works similarly to styling colors in ImGui, but 1053 | // with one important difference. Like ImGui, all style colors are stored in an 1054 | // indexable array in ImPlotStyle. You can permanently modify these values through 1055 | // GetStyle().Colors, or temporarily modify them with Push/Pop functions below. 1056 | // However, by default all style colors in ImPlot default to a special color 1057 | // IMPLOT_AUTO_COL. The behavior of this color depends upon the style color to 1058 | // which it as applied: 1059 | // 1060 | // 1) For style colors associated with plot items (e.g. ImPlotCol_Line), 1061 | // IMPLOT_AUTO_COL tells ImPlot to color the item with the next unused 1062 | // color in the current colormap. Thus, every item will have a different 1063 | // color up to the number of colors in the colormap, at which point the 1064 | // colormap will roll over. For most use cases, you should not need to 1065 | // set these style colors to anything but IMPLOT_COL_AUTO; you are 1066 | // probably better off changing the current colormap. However, if you 1067 | // need to explicitly color a particular item you may either Push/Pop 1068 | // the style color around the item in question, or use the SetNextXXXStyle 1069 | // API below. If you permanently set one of these style colors to a specific 1070 | // color, or forget to call Pop, then all subsequent items will be styled 1071 | // with the color you set. 1072 | // 1073 | // 2) For style colors associated with plot styling (e.g. ImPlotCol_PlotBg), 1074 | // IMPLOT_AUTO_COL tells ImPlot to set that color from color data in your 1075 | // **ImGuiStyle**. The ImGuiCol_ that these style colors default to are 1076 | // detailed above, and in general have been mapped to produce plots visually 1077 | // consistent with your current ImGui style. Of course, you are free to 1078 | // manually set these colors to whatever you like, and further can Push/Pop 1079 | // them around individual plots for plot-specific styling (e.g. coloring axes). 1080 | 1081 | // Provides access to plot style structure for permanant modifications to colors, sizes, etc. 1082 | IMPLOT_API ImPlotStyle& GetStyle(); 1083 | 1084 | // Style plot colors for current ImGui style (default). 1085 | IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = nullptr); 1086 | // Style plot colors for ImGui "Classic". 1087 | IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = nullptr); 1088 | // Style plot colors for ImGui "Dark". 1089 | IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = nullptr); 1090 | // Style plot colors for ImGui "Light". 1091 | IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = nullptr); 1092 | 1093 | // Use PushStyleX to temporarily modify your ImPlotStyle. The modification 1094 | // will last until the matching call to PopStyleX. You MUST call a pop for 1095 | // every push, otherwise you will leak memory! This behaves just like ImGui. 1096 | 1097 | // Temporarily modify a style color. Don't forget to call PopStyleColor! 1098 | IMPLOT_API void PushStyleColor(ImPlotCol idx, ImU32 col); 1099 | IMPLOT_API void PushStyleColor(ImPlotCol idx, const ImVec4& col); 1100 | // Undo temporary style color modification(s). Undo multiple pushes at once by increasing count. 1101 | IMPLOT_API void PopStyleColor(int count = 1); 1102 | 1103 | // Temporarily modify a style variable of float type. Don't forget to call PopStyleVar! 1104 | IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, float val); 1105 | // Temporarily modify a style variable of int type. Don't forget to call PopStyleVar! 1106 | IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, int val); 1107 | // Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar! 1108 | IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val); 1109 | // Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count. 1110 | IMPLOT_API void PopStyleVar(int count = 1); 1111 | 1112 | // The following can be used to modify the style of the next plot item ONLY. They do 1113 | // NOT require calls to PopStyleX. Leave style attributes you don't want modified to 1114 | // IMPLOT_AUTO or IMPLOT_AUTO_COL. Automatic styles will be deduced from the current 1115 | // values in your ImPlotStyle or from Colormap data. 1116 | 1117 | // Set the line color and weight for the next item only. 1118 | IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); 1119 | // Set the fill color for the next item only. 1120 | IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO); 1121 | // Set the marker style for the next item only. 1122 | IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); 1123 | // Set the error bar style for the next item only. 1124 | IMPLOT_API void SetNextErrorBarStyle(const ImVec4& col = IMPLOT_AUTO_COL, float size = IMPLOT_AUTO, float weight = IMPLOT_AUTO); 1125 | 1126 | // Gets the last item primary color (i.e. its legend icon color) 1127 | IMPLOT_API ImVec4 GetLastItemColor(); 1128 | 1129 | // Returns the null terminated string name for an ImPlotCol. 1130 | IMPLOT_API const char* GetStyleColorName(ImPlotCol idx); 1131 | // Returns the null terminated string name for an ImPlotMarker. 1132 | IMPLOT_API const char* GetMarkerName(ImPlotMarker idx); 1133 | 1134 | //----------------------------------------------------------------------------- 1135 | // [SECTION] Colormaps 1136 | //----------------------------------------------------------------------------- 1137 | 1138 | // Item styling is based on colormaps when the relevant ImPlotCol_XXX is set to 1139 | // IMPLOT_AUTO_COL (default). Several built-in colormaps are available. You can 1140 | // add and then push/pop your own colormaps as well. To permanently set a colormap, 1141 | // modify the Colormap index member of your ImPlotStyle. 1142 | 1143 | // Colormap data will be ignored and a custom color will be used if you have done one of the following: 1144 | // 1) Modified an item style color in your ImPlotStyle to anything other than IMPLOT_AUTO_COL. 1145 | // 2) Pushed an item style color using PushStyleColor(). 1146 | // 3) Set the next item style with a SetNextXXXStyle function. 1147 | 1148 | // Add a new colormap. The color data will be copied. The colormap can be used by pushing either the returned index or the 1149 | // string name with PushColormap. The colormap name must be unique and the size must be greater than 1. You will receive 1150 | // an assert otherwise! By default colormaps are considered to be qualitative (i.e. discrete). If you want to create a 1151 | // continuous colormap, set #qual=false. This will treat the colors you provide as keys, and ImPlot will build a linearly 1152 | // interpolated lookup table. The memory footprint of this table will be exactly ((size-1)*255+1)*4 bytes. 1153 | IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImVec4* cols, int size, bool qual=true); 1154 | IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int size, bool qual=true); 1155 | 1156 | // Returns the number of available colormaps (i.e. the built-in + user-added count). 1157 | IMPLOT_API int GetColormapCount(); 1158 | // Returns a null terminated string name for a colormap given an index. Returns nullptr if index is invalid. 1159 | IMPLOT_API const char* GetColormapName(ImPlotColormap cmap); 1160 | // Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid. 1161 | IMPLOT_API ImPlotColormap GetColormapIndex(const char* name); 1162 | 1163 | // Temporarily switch to one of the built-in (i.e. ImPlotColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap! 1164 | IMPLOT_API void PushColormap(ImPlotColormap cmap); 1165 | // Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc. or a string you provided to AddColormap. Don't forget to call PopColormap! 1166 | IMPLOT_API void PushColormap(const char* name); 1167 | // Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count. 1168 | IMPLOT_API void PopColormap(int count = 1); 1169 | 1170 | // Returns the next color from the current colormap and advances the colormap for the current plot. 1171 | // Can also be used with no return value to skip colors if desired. You need to call this between Begin/EndPlot! 1172 | IMPLOT_API ImVec4 NextColormapColor(); 1173 | 1174 | // Colormap utils. If cmap = IMPLOT_AUTO (default), the current colormap is assumed. 1175 | // Pass an explicit colormap index (built-in or user-added) to specify otherwise. 1176 | 1177 | // Returns the size of a colormap. 1178 | IMPLOT_API int GetColormapSize(ImPlotColormap cmap = IMPLOT_AUTO); 1179 | // Returns a color from a colormap given an index >= 0 (modulo will be performed). 1180 | IMPLOT_API ImVec4 GetColormapColor(int idx, ImPlotColormap cmap = IMPLOT_AUTO); 1181 | // Sample a color from the current colormap given t between 0 and 1. 1182 | IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO); 1183 | 1184 | // Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed. 1185 | IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO); 1186 | // Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1]. 1187 | IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO); 1188 | // Shows a button with a colormap gradient brackground. 1189 | IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO); 1190 | 1191 | // When items in a plot sample their color from a colormap, the color is cached and does not change 1192 | // unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted, 1193 | // item colors will NOT update. If you need item colors to resample the new colormap, then use this 1194 | // function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot 1195 | // will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the 1196 | // latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever 1197 | // need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo). 1198 | IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr); 1199 | 1200 | //----------------------------------------------------------------------------- 1201 | // [SECTION] Input Mapping 1202 | //----------------------------------------------------------------------------- 1203 | 1204 | // Provides access to input mapping structure for permanant modifications to controls for pan, select, etc. 1205 | IMPLOT_API ImPlotInputMap& GetInputMap(); 1206 | 1207 | // Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. 1208 | IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = nullptr); 1209 | // Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. 1210 | IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = nullptr); 1211 | 1212 | //----------------------------------------------------------------------------- 1213 | // [SECTION] Miscellaneous 1214 | //----------------------------------------------------------------------------- 1215 | 1216 | // Render icons similar to those that appear in legends (nifty for data lists). 1217 | IMPLOT_API void ItemIcon(const ImVec4& col); 1218 | IMPLOT_API void ItemIcon(ImU32 col); 1219 | IMPLOT_API void ColormapIcon(ImPlotColormap cmap); 1220 | 1221 | // Get the plot draw list for custom rendering to the current plot area. Call between Begin/EndPlot. 1222 | IMPLOT_API ImDrawList* GetPlotDrawList(); 1223 | // Push clip rect for rendering to current plot area. The rect can be expanded or contracted by #expand pixels. Call between Begin/EndPlot. 1224 | IMPLOT_API void PushPlotClipRect(float expand=0); 1225 | // Pop plot clip rect. Call between Begin/EndPlot. 1226 | IMPLOT_API void PopPlotClipRect(); 1227 | 1228 | // Shows ImPlot style selector dropdown menu. 1229 | IMPLOT_API bool ShowStyleSelector(const char* label); 1230 | // Shows ImPlot colormap selector dropdown menu. 1231 | IMPLOT_API bool ShowColormapSelector(const char* label); 1232 | // Shows ImPlot input map selector dropdown menu. 1233 | IMPLOT_API bool ShowInputMapSelector(const char* label); 1234 | // Shows ImPlot style editor block (not a window). 1235 | IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = nullptr); 1236 | // Add basic help/info block for end users (not a window). 1237 | IMPLOT_API void ShowUserGuide(); 1238 | // Shows ImPlot metrics/debug information window. 1239 | IMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr); 1240 | 1241 | //----------------------------------------------------------------------------- 1242 | // [SECTION] Demo 1243 | //----------------------------------------------------------------------------- 1244 | 1245 | // Shows the ImPlot demo window (add implot_demo.cpp to your sources!) 1246 | IMPLOT_API void ShowDemoWindow(bool* p_open = nullptr); 1247 | 1248 | } // namespace ImPlot 1249 | 1250 | //----------------------------------------------------------------------------- 1251 | // [SECTION] Obsolete API 1252 | //----------------------------------------------------------------------------- 1253 | 1254 | // The following functions will be removed! Keep your copy of implot up to date! 1255 | // Occasionally set '#define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS' to stay ahead. 1256 | // If you absolutely must use these functions and do not want to receive compiler 1257 | // warnings, set '#define IMPLOT_DISABLE_OBSOLETE_WARNINGS'. 1258 | 1259 | #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS 1260 | 1261 | #ifndef IMPLOT_DISABLE_DEPRECATED_WARNINGS 1262 | #if __cplusplus > 201402L 1263 | #define IMPLOT_DEPRECATED(method) [[deprecated]] method 1264 | #elif defined( __GNUC__ ) && !defined( __INTEL_COMPILER ) && ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) ) 1265 | #define IMPLOT_DEPRECATED(method) method __attribute__( ( deprecated ) ) 1266 | #elif defined( _MSC_VER ) 1267 | #define IMPLOT_DEPRECATED(method) __declspec(deprecated) method 1268 | #else 1269 | #define IMPLOT_DEPRECATED(method) method 1270 | #endif 1271 | #else 1272 | #define IMPLOT_DEPRECATED(method) method 1273 | #endif 1274 | 1275 | enum ImPlotFlagsObsolete_ { 1276 | ImPlotFlags_YAxis2 = 1 << 20, 1277 | ImPlotFlags_YAxis3 = 1 << 21, 1278 | }; 1279 | 1280 | namespace ImPlot { 1281 | 1282 | // OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0 1283 | IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id, 1284 | const char* x_label, // = nullptr, 1285 | const char* y_label, // = nullptr, 1286 | const ImVec2& size = ImVec2(-1,0), 1287 | ImPlotFlags flags = ImPlotFlags_None, 1288 | ImPlotAxisFlags x_flags = 0, 1289 | ImPlotAxisFlags y_flags = 0, 1290 | ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault, 1291 | ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault, 1292 | const char* y2_label = nullptr, 1293 | const char* y3_label = nullptr) ); 1294 | 1295 | } // namespace ImPlot 1296 | 1297 | #endif 1298 | -------------------------------------------------------------------------------- /implot_internal.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2023 Evan Pezent 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // ImPlot v0.17 24 | 25 | // You may use this file to debug, understand or extend ImPlot features but we 26 | // don't provide any guarantee of forward compatibility! 27 | 28 | //----------------------------------------------------------------------------- 29 | // [SECTION] Header Mess 30 | //----------------------------------------------------------------------------- 31 | 32 | #pragma once 33 | 34 | #include 35 | #include "imgui_internal.h" 36 | 37 | #ifndef IMPLOT_VERSION 38 | #error Must include implot.h before implot_internal.h 39 | #endif 40 | 41 | 42 | // Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize() 43 | #if (IMGUI_VERSION_NUM < 18303) 44 | #define GetBufSize GetSize 45 | #endif 46 | 47 | //----------------------------------------------------------------------------- 48 | // [SECTION] Constants 49 | //----------------------------------------------------------------------------- 50 | 51 | // Constants can be changed unless stated otherwise. We may move some of these 52 | // to ImPlotStyleVar_ over time. 53 | 54 | // Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS) 55 | #define IMPLOT_MIN_TIME 0 56 | // Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS) 57 | #define IMPLOT_MAX_TIME 32503680000 58 | // Default label format for axis labels 59 | #define IMPLOT_LABEL_FORMAT "%g" 60 | // Max character size for tick labels 61 | #define IMPLOT_LABEL_MAX_SIZE 32 62 | 63 | //----------------------------------------------------------------------------- 64 | // [SECTION] Macros 65 | //----------------------------------------------------------------------------- 66 | 67 | #define IMPLOT_NUM_X_AXES ImAxis_Y1 68 | #define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES) 69 | 70 | // Split ImU32 color into RGB components [0 255] 71 | #define IM_COL32_SPLIT_RGB(col,r,g,b) \ 72 | ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \ 73 | ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \ 74 | ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF); 75 | 76 | //----------------------------------------------------------------------------- 77 | // [SECTION] Forward Declarations 78 | //----------------------------------------------------------------------------- 79 | 80 | struct ImPlotTick; 81 | struct ImPlotAxis; 82 | struct ImPlotAxisColor; 83 | struct ImPlotItem; 84 | struct ImPlotLegend; 85 | struct ImPlotPlot; 86 | struct ImPlotNextPlotData; 87 | struct ImPlotTicker; 88 | 89 | //----------------------------------------------------------------------------- 90 | // [SECTION] Context Pointer 91 | //----------------------------------------------------------------------------- 92 | 93 | #ifndef GImPlot 94 | extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer 95 | #endif 96 | 97 | //----------------------------------------------------------------------------- 98 | // [SECTION] Generic Helpers 99 | //----------------------------------------------------------------------------- 100 | 101 | // Computes the common (base-10) logarithm 102 | static inline float ImLog10(float x) { return log10f(x); } 103 | static inline double ImLog10(double x) { return log10(x); } 104 | static inline float ImSinh(float x) { return sinhf(x); } 105 | static inline double ImSinh(double x) { return sinh(x); } 106 | static inline float ImAsinh(float x) { return asinhf(x); } 107 | static inline double ImAsinh(double x) { return asinh(x); } 108 | // Returns true if a flag is set 109 | template 110 | static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; } 111 | // Flips a flag in a flagset 112 | template 113 | static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; } 114 | // Linearly remaps x from [x0 x1] to [y0 y1]. 115 | template 116 | static inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); } 117 | // Linear rempas x from [x0 x1] to [0 1] 118 | template 119 | static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); } 120 | // Returns always positive modulo (assumes r != 0) 121 | static inline int ImPosMod(int l, int r) { return (l % r + r) % r; } 122 | // Returns true if val is NAN 123 | static inline bool ImNan(double val) { return isnan(val); } 124 | // Returns true if val is NAN or INFINITY 125 | static inline bool ImNanOrInf(double val) { return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); } 126 | // Turns NANs to 0s 127 | static inline double ImConstrainNan(double val) { return ImNan(val) ? 0 : val; } 128 | // Turns infinity to floating point maximums 129 | static inline double ImConstrainInf(double val) { return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; } 130 | // Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?) 131 | static inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; } 132 | // Turns numbers less than 0 to zero 133 | static inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); } 134 | // True if two numbers are approximately equal using units in the last place. 135 | static inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; } 136 | // Finds min value in an unsorted array 137 | template 138 | static inline T ImMinArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] < m) { m = values[i]; } } return m; } 139 | // Finds the max value in an unsorted array 140 | template 141 | static inline T ImMaxArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] > m) { m = values[i]; } } return m; } 142 | // Finds the min and max value in an unsorted array 143 | template 144 | static inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_out) { 145 | T Min = values[0]; T Max = values[0]; 146 | for (int i = 1; i < count; ++i) { 147 | if (values[i] < Min) { Min = values[i]; } 148 | if (values[i] > Max) { Max = values[i]; } 149 | } 150 | *min_out = Min; *max_out = Max; 151 | } 152 | // Finds the sim of an array 153 | template 154 | static inline T ImSum(const T* values, int count) { 155 | T sum = 0; 156 | for (int i = 0; i < count; ++i) 157 | sum += values[i]; 158 | return sum; 159 | } 160 | // Finds the mean of an array 161 | template 162 | static inline double ImMean(const T* values, int count) { 163 | double den = 1.0 / count; 164 | double mu = 0; 165 | for (int i = 0; i < count; ++i) 166 | mu += (double)values[i] * den; 167 | return mu; 168 | } 169 | // Finds the sample standard deviation of an array 170 | template 171 | static inline double ImStdDev(const T* values, int count) { 172 | double den = 1.0 / (count - 1.0); 173 | double mu = ImMean(values, count); 174 | double x = 0; 175 | for (int i = 0; i < count; ++i) 176 | x += ((double)values[i] - mu) * ((double)values[i] - mu) * den; 177 | return sqrt(x); 178 | } 179 | // Mix color a and b by factor s in [0 256] 180 | static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) { 181 | #ifdef IMPLOT_MIX64 182 | const ImU32 af = 256-s; 183 | const ImU32 bf = s; 184 | const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24); 185 | const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24); 186 | const ImU64 mix = (al * af + bl * bf); 187 | return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8); 188 | #else 189 | const ImU32 af = 256-s; 190 | const ImU32 bf = s; 191 | const ImU32 al = (a & 0x00ff00ff); 192 | const ImU32 ah = (a & 0xff00ff00) >> 8; 193 | const ImU32 bl = (b & 0x00ff00ff); 194 | const ImU32 bh = (b & 0xff00ff00) >> 8; 195 | const ImU32 ml = (al * af + bl * bf); 196 | const ImU32 mh = (ah * af + bh * bf); 197 | return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8); 198 | #endif 199 | } 200 | 201 | // Lerp across an array of 32-bit collors given t in [0.0 1.0] 202 | static inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) { 203 | int i1 = (int)((size - 1 ) * t); 204 | int i2 = i1 + 1; 205 | if (i2 == size || size == 1) 206 | return colors[i1]; 207 | float den = 1.0f / (size - 1); 208 | float t1 = i1 * den; 209 | float t2 = i2 * den; 210 | float tr = ImRemap01(t, t1, t2); 211 | return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256)); 212 | } 213 | 214 | // Set alpha channel of 32-bit color from float in range [0.0 1.0] 215 | static inline ImU32 ImAlphaU32(ImU32 col, float alpha) { 216 | return col & ~((ImU32)((1.0f-alpha)*255)< 221 | static inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) { 222 | return min_a <= max_b && min_b <= max_a; 223 | } 224 | 225 | //----------------------------------------------------------------------------- 226 | // [SECTION] ImPlot Enums 227 | //----------------------------------------------------------------------------- 228 | 229 | typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_ 230 | typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_ 231 | typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_ 232 | 233 | enum ImPlotTimeUnit_ { 234 | ImPlotTimeUnit_Us, // microsecond 235 | ImPlotTimeUnit_Ms, // millisecond 236 | ImPlotTimeUnit_S, // second 237 | ImPlotTimeUnit_Min, // minute 238 | ImPlotTimeUnit_Hr, // hour 239 | ImPlotTimeUnit_Day, // day 240 | ImPlotTimeUnit_Mo, // month 241 | ImPlotTimeUnit_Yr, // year 242 | ImPlotTimeUnit_COUNT 243 | }; 244 | 245 | enum ImPlotDateFmt_ { // default [ ISO 8601 ] 246 | ImPlotDateFmt_None = 0, 247 | ImPlotDateFmt_DayMo, // 10/3 [ --10-03 ] 248 | ImPlotDateFmt_DayMoYr, // 10/3/91 [ 1991-10-03 ] 249 | ImPlotDateFmt_MoYr, // Oct 1991 [ 1991-10 ] 250 | ImPlotDateFmt_Mo, // Oct [ --10 ] 251 | ImPlotDateFmt_Yr // 1991 [ 1991 ] 252 | }; 253 | 254 | enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ] 255 | ImPlotTimeFmt_None = 0, 256 | ImPlotTimeFmt_Us, // .428 552 [ .428 552 ] 257 | ImPlotTimeFmt_SUs, // :29.428 552 [ :29.428 552 ] 258 | ImPlotTimeFmt_SMs, // :29.428 [ :29.428 ] 259 | ImPlotTimeFmt_S, // :29 [ :29 ] 260 | ImPlotTimeFmt_MinSMs, // 21:29.428 [ 21:29.428 ] 261 | ImPlotTimeFmt_HrMinSMs, // 7:21:29.428pm [ 19:21:29.428 ] 262 | ImPlotTimeFmt_HrMinS, // 7:21:29pm [ 19:21:29 ] 263 | ImPlotTimeFmt_HrMin, // 7:21pm [ 19:21 ] 264 | ImPlotTimeFmt_Hr // 7pm [ 19:00 ] 265 | }; 266 | 267 | //----------------------------------------------------------------------------- 268 | // [SECTION] Callbacks 269 | //----------------------------------------------------------------------------- 270 | 271 | typedef void (*ImPlotLocator)(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); 272 | 273 | //----------------------------------------------------------------------------- 274 | // [SECTION] Structs 275 | //----------------------------------------------------------------------------- 276 | 277 | // Combined date/time format spec 278 | struct ImPlotDateTimeSpec { 279 | ImPlotDateTimeSpec() {} 280 | ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) { 281 | Date = date_fmt; 282 | Time = time_fmt; 283 | UseISO8601 = use_iso_8601; 284 | Use24HourClock = use_24_hr_clk; 285 | } 286 | ImPlotDateFmt Date; 287 | ImPlotTimeFmt Time; 288 | bool UseISO8601; 289 | bool Use24HourClock; 290 | }; 291 | 292 | // Two part timestamp struct. 293 | struct ImPlotTime { 294 | time_t S; // second part 295 | int Us; // microsecond part 296 | ImPlotTime() { S = 0; Us = 0; } 297 | ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; } 298 | void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; } 299 | double ToDouble() const { return (double)S + (double)Us / 1000000.0; } 300 | static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); } 301 | }; 302 | 303 | static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs) 304 | { return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); } 305 | static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs) 306 | { return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); } 307 | static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs) 308 | { return lhs.S == rhs.S && lhs.Us == rhs.Us; } 309 | static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs) 310 | { return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; } 311 | static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs) 312 | { return rhs < lhs; } 313 | static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs) 314 | { return lhs < rhs || lhs == rhs; } 315 | static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs) 316 | { return lhs > rhs || lhs == rhs; } 317 | 318 | // Colormap data storage 319 | struct ImPlotColormapData { 320 | ImVector Keys; 321 | ImVector KeyCounts; 322 | ImVector KeyOffsets; 323 | ImVector Tables; 324 | ImVector TableSizes; 325 | ImVector TableOffsets; 326 | ImGuiTextBuffer Text; 327 | ImVector TextOffsets; 328 | ImVector Quals; 329 | ImGuiStorage Map; 330 | int Count; 331 | 332 | ImPlotColormapData() { Count = 0; } 333 | 334 | int Append(const char* name, const ImU32* keys, int count, bool qual) { 335 | if (GetIndex(name) != -1) 336 | return -1; 337 | KeyOffsets.push_back(Keys.size()); 338 | KeyCounts.push_back(count); 339 | Keys.reserve(Keys.size()+count); 340 | for (int i = 0; i < count; ++i) 341 | Keys.push_back(keys[i]); 342 | TextOffsets.push_back(Text.size()); 343 | Text.append(name, name + strlen(name) + 1); 344 | Quals.push_back(qual); 345 | ImGuiID id = ImHashStr(name); 346 | int idx = Count++; 347 | Map.SetInt(id,idx); 348 | _AppendTable(idx); 349 | return idx; 350 | } 351 | 352 | void _AppendTable(ImPlotColormap cmap) { 353 | int key_count = GetKeyCount(cmap); 354 | const ImU32* keys = GetKeys(cmap); 355 | int off = Tables.size(); 356 | TableOffsets.push_back(off); 357 | if (IsQual(cmap)) { 358 | Tables.reserve(key_count); 359 | for (int i = 0; i < key_count; ++i) 360 | Tables.push_back(keys[i]); 361 | TableSizes.push_back(key_count); 362 | } 363 | else { 364 | int max_size = 255 * (key_count-1) + 1; 365 | Tables.reserve(off + max_size); 366 | // ImU32 last = keys[0]; 367 | // Tables.push_back(last); 368 | // int n = 1; 369 | for (int i = 0; i < key_count-1; ++i) { 370 | for (int s = 0; s < 255; ++s) { 371 | ImU32 a = keys[i]; 372 | ImU32 b = keys[i+1]; 373 | ImU32 c = ImMixU32(a,b,s); 374 | // if (c != last) { 375 | Tables.push_back(c); 376 | // last = c; 377 | // n++; 378 | // } 379 | } 380 | } 381 | ImU32 c = keys[key_count-1]; 382 | // if (c != last) { 383 | Tables.push_back(c); 384 | // n++; 385 | // } 386 | // TableSizes.push_back(n); 387 | TableSizes.push_back(max_size); 388 | } 389 | } 390 | 391 | void RebuildTables() { 392 | Tables.resize(0); 393 | TableSizes.resize(0); 394 | TableOffsets.resize(0); 395 | for (int i = 0; i < Count; ++i) 396 | _AppendTable(i); 397 | } 398 | 399 | inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; } 400 | inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; } 401 | inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); } 402 | 403 | inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; } 404 | inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; } 405 | inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; } 406 | inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); } 407 | 408 | inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; } 409 | inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; } 410 | inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; } 411 | 412 | inline ImU32 LerpTable(ImPlotColormap cmap, float t) const { 413 | int off = TableOffsets[cmap]; 414 | int siz = TableSizes[cmap]; 415 | int idx = Quals[cmap] ? ImClamp((int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f); 416 | return Tables[off + idx]; 417 | } 418 | }; 419 | 420 | // ImPlotPoint with positive/negative error values 421 | struct ImPlotPointError { 422 | double X, Y, Neg, Pos; 423 | ImPlotPointError(double x, double y, double neg, double pos) { 424 | X = x; Y = y; Neg = neg; Pos = pos; 425 | } 426 | }; 427 | 428 | // Interior plot label/annotation 429 | struct ImPlotAnnotation { 430 | ImVec2 Pos; 431 | ImVec2 Offset; 432 | ImU32 ColorBg; 433 | ImU32 ColorFg; 434 | int TextOffset; 435 | bool Clamp; 436 | ImPlotAnnotation() { 437 | ColorBg = ColorFg = 0; 438 | TextOffset = 0; 439 | Clamp = false; 440 | } 441 | }; 442 | 443 | // Collection of plot labels 444 | struct ImPlotAnnotationCollection { 445 | 446 | ImVector Annotations; 447 | ImGuiTextBuffer TextBuffer; 448 | int Size; 449 | 450 | ImPlotAnnotationCollection() { Reset(); } 451 | 452 | void AppendV(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, va_list args) IM_FMTLIST(7) { 453 | ImPlotAnnotation an; 454 | an.Pos = pos; an.Offset = off; 455 | an.ColorBg = bg; an.ColorFg = fg; 456 | an.TextOffset = TextBuffer.size(); 457 | an.Clamp = clamp; 458 | Annotations.push_back(an); 459 | TextBuffer.appendfv(fmt, args); 460 | const char nul[] = ""; 461 | TextBuffer.append(nul,nul+1); 462 | Size++; 463 | } 464 | 465 | void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, ...) IM_FMTARGS(7) { 466 | va_list args; 467 | va_start(args, fmt); 468 | AppendV(pos, off, bg, fg, clamp, fmt, args); 469 | va_end(args); 470 | } 471 | 472 | const char* GetText(int idx) { 473 | return TextBuffer.Buf.Data + Annotations[idx].TextOffset; 474 | } 475 | 476 | void Reset() { 477 | Annotations.shrink(0); 478 | TextBuffer.Buf.shrink(0); 479 | Size = 0; 480 | } 481 | }; 482 | 483 | struct ImPlotTag { 484 | ImAxis Axis; 485 | double Value; 486 | ImU32 ColorBg; 487 | ImU32 ColorFg; 488 | int TextOffset; 489 | }; 490 | 491 | struct ImPlotTagCollection { 492 | 493 | ImVector Tags; 494 | ImGuiTextBuffer TextBuffer; 495 | int Size; 496 | 497 | ImPlotTagCollection() { Reset(); } 498 | 499 | void AppendV(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, va_list args) IM_FMTLIST(6) { 500 | ImPlotTag tag; 501 | tag.Axis = axis; 502 | tag.Value = value; 503 | tag.ColorBg = bg; 504 | tag.ColorFg = fg; 505 | tag.TextOffset = TextBuffer.size(); 506 | Tags.push_back(tag); 507 | TextBuffer.appendfv(fmt, args); 508 | const char nul[] = ""; 509 | TextBuffer.append(nul,nul+1); 510 | Size++; 511 | } 512 | 513 | void Append(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, ...) IM_FMTARGS(6) { 514 | va_list args; 515 | va_start(args, fmt); 516 | AppendV(axis, value, bg, fg, fmt, args); 517 | va_end(args); 518 | } 519 | 520 | const char* GetText(int idx) { 521 | return TextBuffer.Buf.Data + Tags[idx].TextOffset; 522 | } 523 | 524 | void Reset() { 525 | Tags.shrink(0); 526 | TextBuffer.Buf.shrink(0); 527 | Size = 0; 528 | } 529 | }; 530 | 531 | // Tick mark info 532 | struct ImPlotTick 533 | { 534 | double PlotPos; 535 | float PixelPos; 536 | ImVec2 LabelSize; 537 | int TextOffset; 538 | bool Major; 539 | bool ShowLabel; 540 | int Level; 541 | int Idx; 542 | 543 | ImPlotTick(double value, bool major, int level, bool show_label) { 544 | PixelPos = 0; 545 | PlotPos = value; 546 | Major = major; 547 | ShowLabel = show_label; 548 | Level = level; 549 | TextOffset = -1; 550 | } 551 | }; 552 | 553 | // Collection of ticks 554 | struct ImPlotTicker { 555 | ImVector Ticks; 556 | ImGuiTextBuffer TextBuffer; 557 | ImVec2 MaxSize; 558 | ImVec2 LateSize; 559 | int Levels; 560 | 561 | ImPlotTicker() { 562 | Reset(); 563 | } 564 | 565 | ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) { 566 | ImPlotTick tick(value, major, level, show_label); 567 | if (show_label && label != nullptr) { 568 | tick.TextOffset = TextBuffer.size(); 569 | TextBuffer.append(label, label + strlen(label) + 1); 570 | tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset); 571 | } 572 | return AddTick(tick); 573 | } 574 | 575 | ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) { 576 | ImPlotTick tick(value, major, level, show_label); 577 | if (show_label && formatter != nullptr) { 578 | char buff[IMPLOT_LABEL_MAX_SIZE]; 579 | tick.TextOffset = TextBuffer.size(); 580 | formatter(tick.PlotPos, buff, sizeof(buff), data); 581 | TextBuffer.append(buff, buff + strlen(buff) + 1); 582 | tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset); 583 | } 584 | return AddTick(tick); 585 | } 586 | 587 | inline ImPlotTick& AddTick(ImPlotTick tick) { 588 | if (tick.ShowLabel) { 589 | MaxSize.x = tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x; 590 | MaxSize.y = tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y; 591 | } 592 | tick.Idx = Ticks.size(); 593 | Ticks.push_back(tick); 594 | return Ticks.back(); 595 | } 596 | 597 | const char* GetText(int idx) const { 598 | return TextBuffer.Buf.Data + Ticks[idx].TextOffset; 599 | } 600 | 601 | const char* GetText(const ImPlotTick& tick) { 602 | return GetText(tick.Idx); 603 | } 604 | 605 | void OverrideSizeLate(const ImVec2& size) { 606 | LateSize.x = size.x > LateSize.x ? size.x : LateSize.x; 607 | LateSize.y = size.y > LateSize.y ? size.y : LateSize.y; 608 | } 609 | 610 | void Reset() { 611 | Ticks.shrink(0); 612 | TextBuffer.Buf.shrink(0); 613 | MaxSize = LateSize; 614 | LateSize = ImVec2(0,0); 615 | Levels = 1; 616 | } 617 | 618 | int TickCount() const { 619 | return Ticks.Size; 620 | } 621 | }; 622 | 623 | // Axis state information that must persist after EndPlot 624 | struct ImPlotAxis 625 | { 626 | ImGuiID ID; 627 | ImPlotAxisFlags Flags; 628 | ImPlotAxisFlags PreviousFlags; 629 | ImPlotRange Range; 630 | ImPlotCond RangeCond; 631 | ImPlotScale Scale; 632 | ImPlotRange FitExtents; 633 | ImPlotAxis* OrthoAxis; 634 | ImPlotRange ConstraintRange; 635 | ImPlotRange ConstraintZoom; 636 | 637 | ImPlotTicker Ticker; 638 | ImPlotFormatter Formatter; 639 | void* FormatterData; 640 | char FormatSpec[16]; 641 | ImPlotLocator Locator; 642 | 643 | double* LinkedMin; 644 | double* LinkedMax; 645 | 646 | int PickerLevel; 647 | ImPlotTime PickerTimeMin, PickerTimeMax; 648 | 649 | ImPlotTransform TransformForward; 650 | ImPlotTransform TransformInverse; 651 | void* TransformData; 652 | float PixelMin, PixelMax; 653 | double ScaleMin, ScaleMax; 654 | double ScaleToPixel; 655 | float Datum1, Datum2; 656 | 657 | ImRect HoverRect; 658 | int LabelOffset; 659 | ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi; 660 | 661 | bool Enabled; 662 | bool Vertical; 663 | bool FitThisFrame; 664 | bool HasRange; 665 | bool HasFormatSpec; 666 | bool ShowDefaultTicks; 667 | bool Hovered; 668 | bool Held; 669 | 670 | ImPlotAxis() { 671 | ID = 0; 672 | Flags = PreviousFlags = ImPlotAxisFlags_None; 673 | Range.Min = 0; 674 | Range.Max = 1; 675 | Scale = ImPlotScale_Linear; 676 | TransformForward = TransformInverse = nullptr; 677 | TransformData = nullptr; 678 | FitExtents.Min = HUGE_VAL; 679 | FitExtents.Max = -HUGE_VAL; 680 | OrthoAxis = nullptr; 681 | ConstraintRange = ImPlotRange(-INFINITY,INFINITY); 682 | ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); 683 | LinkedMin = LinkedMax = nullptr; 684 | PickerLevel = 0; 685 | Datum1 = Datum2 = 0; 686 | PixelMin = PixelMax = 0; 687 | LabelOffset = -1; 688 | ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0; 689 | ColorHiLi = IM_COL32_BLACK_TRANS; 690 | Formatter = nullptr; 691 | FormatterData = nullptr; 692 | Locator = nullptr; 693 | Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false; 694 | ShowDefaultTicks = true; 695 | } 696 | 697 | inline void Reset() { 698 | Enabled = false; 699 | Scale = ImPlotScale_Linear; 700 | TransformForward = TransformInverse = nullptr; 701 | TransformData = nullptr; 702 | LabelOffset = -1; 703 | HasFormatSpec = false; 704 | Formatter = nullptr; 705 | FormatterData = nullptr; 706 | Locator = nullptr; 707 | ShowDefaultTicks = true; 708 | FitThisFrame = false; 709 | FitExtents.Min = HUGE_VAL; 710 | FitExtents.Max = -HUGE_VAL; 711 | OrthoAxis = nullptr; 712 | ConstraintRange = ImPlotRange(-INFINITY,INFINITY); 713 | ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); 714 | Ticker.Reset(); 715 | } 716 | 717 | inline bool SetMin(double _min, bool force=false) { 718 | if (!force && IsLockedMin()) 719 | return false; 720 | _min = ImConstrainNan(ImConstrainInf(_min)); 721 | if (_min < ConstraintRange.Min) 722 | _min = ConstraintRange.Min; 723 | double z = Range.Max - _min; 724 | if (z < ConstraintZoom.Min) 725 | _min = Range.Max - ConstraintZoom.Min; 726 | if (z > ConstraintZoom.Max) 727 | _min = Range.Max - ConstraintZoom.Max; 728 | if (_min >= Range.Max) 729 | return false; 730 | Range.Min = _min; 731 | PickerTimeMin = ImPlotTime::FromDouble(Range.Min); 732 | UpdateTransformCache(); 733 | return true; 734 | }; 735 | 736 | inline bool SetMax(double _max, bool force=false) { 737 | if (!force && IsLockedMax()) 738 | return false; 739 | _max = ImConstrainNan(ImConstrainInf(_max)); 740 | if (_max > ConstraintRange.Max) 741 | _max = ConstraintRange.Max; 742 | double z = _max - Range.Min; 743 | if (z < ConstraintZoom.Min) 744 | _max = Range.Min + ConstraintZoom.Min; 745 | if (z > ConstraintZoom.Max) 746 | _max = Range.Min + ConstraintZoom.Max; 747 | if (_max <= Range.Min) 748 | return false; 749 | Range.Max = _max; 750 | PickerTimeMax = ImPlotTime::FromDouble(Range.Max); 751 | UpdateTransformCache(); 752 | return true; 753 | }; 754 | 755 | inline void SetRange(double v1, double v2) { 756 | Range.Min = ImMin(v1,v2); 757 | Range.Max = ImMax(v1,v2); 758 | Constrain(); 759 | PickerTimeMin = ImPlotTime::FromDouble(Range.Min); 760 | PickerTimeMax = ImPlotTime::FromDouble(Range.Max); 761 | UpdateTransformCache(); 762 | } 763 | 764 | inline void SetRange(const ImPlotRange& range) { 765 | SetRange(range.Min, range.Max); 766 | } 767 | 768 | inline void SetAspect(double unit_per_pix) { 769 | double new_size = unit_per_pix * PixelSize(); 770 | double delta = (new_size - Range.Size()) * 0.5; 771 | if (IsLocked()) 772 | return; 773 | else if (IsLockedMin() && !IsLockedMax()) 774 | SetRange(Range.Min, Range.Max + 2*delta); 775 | else if (!IsLockedMin() && IsLockedMax()) 776 | SetRange(Range.Min - 2*delta, Range.Max); 777 | else 778 | SetRange(Range.Min - delta, Range.Max + delta); 779 | } 780 | 781 | inline float PixelSize() const { return ImAbs(PixelMax - PixelMin); } 782 | 783 | inline double GetAspect() const { return Range.Size() / PixelSize(); } 784 | 785 | inline void Constrain() { 786 | Range.Min = ImConstrainNan(ImConstrainInf(Range.Min)); 787 | Range.Max = ImConstrainNan(ImConstrainInf(Range.Max)); 788 | if (Range.Min < ConstraintRange.Min) 789 | Range.Min = ConstraintRange.Min; 790 | if (Range.Max > ConstraintRange.Max) 791 | Range.Max = ConstraintRange.Max; 792 | double z = Range.Size(); 793 | if (z < ConstraintZoom.Min) { 794 | double delta = (ConstraintZoom.Min - z) * 0.5; 795 | Range.Min -= delta; 796 | Range.Max += delta; 797 | } 798 | if (z > ConstraintZoom.Max) { 799 | double delta = (z - ConstraintZoom.Max) * 0.5; 800 | Range.Min += delta; 801 | Range.Max -= delta; 802 | } 803 | if (Range.Max <= Range.Min) 804 | Range.Max = Range.Min + DBL_EPSILON; 805 | } 806 | 807 | inline void UpdateTransformCache() { 808 | ScaleToPixel = (PixelMax - PixelMin) / Range.Size(); 809 | if (TransformForward != nullptr) { 810 | ScaleMin = TransformForward(Range.Min, TransformData); 811 | ScaleMax = TransformForward(Range.Max, TransformData); 812 | } 813 | else { 814 | ScaleMin = Range.Min; 815 | ScaleMax = Range.Max; 816 | } 817 | } 818 | 819 | inline float PlotToPixels(double plt) const { 820 | if (TransformForward != nullptr) { 821 | double s = TransformForward(plt, TransformData); 822 | double t = (s - ScaleMin) / (ScaleMax - ScaleMin); 823 | plt = Range.Min + Range.Size() * t; 824 | } 825 | return (float)(PixelMin + ScaleToPixel * (plt - Range.Min)); 826 | } 827 | 828 | 829 | inline double PixelsToPlot(float pix) const { 830 | double plt = (pix - PixelMin) / ScaleToPixel + Range.Min; 831 | if (TransformInverse != nullptr) { 832 | double t = (plt - Range.Min) / Range.Size(); 833 | double s = t * (ScaleMax - ScaleMin) + ScaleMin; 834 | plt = TransformInverse(s, TransformData); 835 | } 836 | return plt; 837 | } 838 | 839 | inline void ExtendFit(double v) { 840 | if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) { 841 | FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min; 842 | FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max; 843 | } 844 | } 845 | 846 | inline void ExtendFitWith(ImPlotAxis& alt, double v, double v_alt) { 847 | if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt)) 848 | return; 849 | if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) { 850 | FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min; 851 | FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max; 852 | } 853 | } 854 | 855 | inline void ApplyFit(float padding) { 856 | const double ext_size = FitExtents.Size() * 0.5; 857 | FitExtents.Min -= ext_size * padding; 858 | FitExtents.Max += ext_size * padding; 859 | if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min)) 860 | Range.Min = FitExtents.Min; 861 | if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max)) 862 | Range.Max = FitExtents.Max; 863 | if (ImAlmostEqual(Range.Min, Range.Max)) { 864 | Range.Max += 0.5; 865 | Range.Min -= 0.5; 866 | } 867 | Constrain(); 868 | UpdateTransformCache(); 869 | } 870 | 871 | inline bool HasLabel() const { return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel); } 872 | inline bool HasGridLines() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines); } 873 | inline bool HasTickLabels() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); } 874 | inline bool HasTickMarks() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks); } 875 | inline bool WillRender() const { return Enabled && (HasGridLines() || HasTickLabels() || HasTickMarks()); } 876 | inline bool IsOpposite() const { return ImHasFlag(Flags, ImPlotAxisFlags_Opposite); } 877 | inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); } 878 | inline bool IsForeground() const { return ImHasFlag(Flags, ImPlotAxisFlags_Foreground); } 879 | inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); } 880 | inline bool CanInitFit() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; } 881 | inline bool IsRangeLocked() const { return HasRange && RangeCond == ImPlotCond_Always; } 882 | inline bool IsLockedMin() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); } 883 | inline bool IsLockedMax() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); } 884 | inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); } 885 | inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); } 886 | inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); } 887 | inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); } 888 | inline bool HasMenus() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus); } 889 | 890 | inline bool IsPanLocked(bool increasing) { 891 | if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) { 892 | return IsInputLocked(); 893 | } 894 | else { 895 | if (IsLockedMin() || IsLockedMax() || IsAutoFitting()) 896 | return false; 897 | if (increasing) 898 | return Range.Max == ConstraintRange.Max; 899 | else 900 | return Range.Min == ConstraintRange.Min; 901 | } 902 | } 903 | 904 | void PushLinks() { 905 | if (LinkedMin) { *LinkedMin = Range.Min; } 906 | if (LinkedMax) { *LinkedMax = Range.Max; } 907 | } 908 | 909 | void PullLinks() { 910 | if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); } 911 | else if (LinkedMin) { SetMin(*LinkedMin,true); } 912 | else if (LinkedMax) { SetMax(*LinkedMax,true); } 913 | } 914 | }; 915 | 916 | // Align plots group data 917 | struct ImPlotAlignmentData { 918 | bool Vertical; 919 | float PadA; 920 | float PadB; 921 | float PadAMax; 922 | float PadBMax; 923 | ImPlotAlignmentData() { 924 | Vertical = true; 925 | PadA = PadB = PadAMax = PadBMax = 0; 926 | } 927 | void Begin() { PadAMax = PadBMax = 0; } 928 | void Update(float& pad_a, float& pad_b, float& delta_a, float& delta_b) { 929 | float bak_a = pad_a; float bak_b = pad_b; 930 | if (PadAMax < pad_a) { PadAMax = pad_a; } 931 | if (PadBMax < pad_b) { PadBMax = pad_b; } 932 | if (pad_a < PadA) { pad_a = PadA; delta_a = pad_a - bak_a; } else { delta_a = 0; } 933 | if (pad_b < PadB) { pad_b = PadB; delta_b = pad_b - bak_b; } else { delta_b = 0; } 934 | } 935 | void End() { PadA = PadAMax; PadB = PadBMax; } 936 | void Reset() { PadA = PadB = PadAMax = PadBMax = 0; } 937 | }; 938 | 939 | // State information for Plot items 940 | struct ImPlotItem 941 | { 942 | ImGuiID ID; 943 | ImU32 Color; 944 | ImRect LegendHoverRect; 945 | int NameOffset; 946 | bool Show; 947 | bool LegendHovered; 948 | bool SeenThisFrame; 949 | 950 | ImPlotItem() { 951 | ID = 0; 952 | Color = IM_COL32_WHITE; 953 | NameOffset = -1; 954 | Show = true; 955 | SeenThisFrame = false; 956 | LegendHovered = false; 957 | } 958 | 959 | ~ImPlotItem() { ID = 0; } 960 | }; 961 | 962 | // Holds Legend state 963 | struct ImPlotLegend 964 | { 965 | ImPlotLegendFlags Flags; 966 | ImPlotLegendFlags PreviousFlags; 967 | ImPlotLocation Location; 968 | ImPlotLocation PreviousLocation; 969 | ImVec2 Scroll; 970 | ImVector Indices; 971 | ImGuiTextBuffer Labels; 972 | ImRect Rect; 973 | ImRect RectClamped; 974 | bool Hovered; 975 | bool Held; 976 | bool CanGoInside; 977 | 978 | ImPlotLegend() { 979 | Flags = PreviousFlags = ImPlotLegendFlags_None; 980 | CanGoInside = true; 981 | Hovered = Held = false; 982 | Location = PreviousLocation = ImPlotLocation_NorthWest; 983 | Scroll = ImVec2(0,0); 984 | } 985 | 986 | void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); } 987 | }; 988 | 989 | // Holds Items and Legend data 990 | struct ImPlotItemGroup 991 | { 992 | ImGuiID ID; 993 | ImPlotLegend Legend; 994 | ImPool ItemPool; 995 | int ColormapIdx; 996 | 997 | ImPlotItemGroup() { ID = 0; ColormapIdx = 0; } 998 | 999 | int GetItemCount() const { return ItemPool.GetBufSize(); } 1000 | ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ } 1001 | ImPlotItem* GetItem(ImGuiID id) { return ItemPool.GetByKey(id); } 1002 | ImPlotItem* GetItem(const char* label_id) { return GetItem(GetItemID(label_id)); } 1003 | ImPlotItem* GetOrAddItem(ImGuiID id) { return ItemPool.GetOrAddByKey(id); } 1004 | ImPlotItem* GetItemByIndex(int i) { return ItemPool.GetByIndex(i); } 1005 | int GetItemIndex(ImPlotItem* item) { return ItemPool.GetIndex(item); } 1006 | int GetLegendCount() const { return Legend.Indices.size(); } 1007 | ImPlotItem* GetLegendItem(int i) { return ItemPool.GetByIndex(Legend.Indices[i]); } 1008 | const char* GetLegendLabel(int i) { return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; } 1009 | void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; } 1010 | }; 1011 | 1012 | // Holds Plot state information that must persist after EndPlot 1013 | struct ImPlotPlot 1014 | { 1015 | ImGuiID ID; 1016 | ImPlotFlags Flags; 1017 | ImPlotFlags PreviousFlags; 1018 | ImPlotLocation MouseTextLocation; 1019 | ImPlotMouseTextFlags MouseTextFlags; 1020 | ImPlotAxis Axes[ImAxis_COUNT]; 1021 | ImGuiTextBuffer TextBuffer; 1022 | ImPlotItemGroup Items; 1023 | ImAxis CurrentX; 1024 | ImAxis CurrentY; 1025 | ImRect FrameRect; 1026 | ImRect CanvasRect; 1027 | ImRect PlotRect; 1028 | ImRect AxesRect; 1029 | ImRect SelectRect; 1030 | ImVec2 SelectStart; 1031 | int TitleOffset; 1032 | bool JustCreated; 1033 | bool Initialized; 1034 | bool SetupLocked; 1035 | bool FitThisFrame; 1036 | bool Hovered; 1037 | bool Held; 1038 | bool Selecting; 1039 | bool Selected; 1040 | bool ContextLocked; 1041 | 1042 | ImPlotPlot() { 1043 | Flags = PreviousFlags = ImPlotFlags_None; 1044 | for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) 1045 | XAxis(i).Vertical = false; 1046 | for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) 1047 | YAxis(i).Vertical = true; 1048 | SelectStart = ImVec2(0,0); 1049 | CurrentX = ImAxis_X1; 1050 | CurrentY = ImAxis_Y1; 1051 | MouseTextLocation = ImPlotLocation_South | ImPlotLocation_East; 1052 | MouseTextFlags = ImPlotMouseTextFlags_None; 1053 | TitleOffset = -1; 1054 | JustCreated = true; 1055 | Initialized = SetupLocked = FitThisFrame = false; 1056 | Hovered = Held = Selected = Selecting = ContextLocked = false; 1057 | } 1058 | 1059 | inline bool IsInputLocked() const { 1060 | for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) { 1061 | if (!XAxis(i).IsInputLocked()) 1062 | return false; 1063 | } 1064 | for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) { 1065 | if (!YAxis(i).IsInputLocked()) 1066 | return false; 1067 | } 1068 | return true; 1069 | } 1070 | 1071 | inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); } 1072 | 1073 | inline void SetTitle(const char* title) { 1074 | if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) { 1075 | TitleOffset = TextBuffer.size(); 1076 | TextBuffer.append(title, title + strlen(title) + 1); 1077 | } 1078 | else { 1079 | TitleOffset = -1; 1080 | } 1081 | } 1082 | inline bool HasTitle() const { return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); } 1083 | inline const char* GetTitle() const { return TextBuffer.Buf.Data + TitleOffset; } 1084 | 1085 | inline ImPlotAxis& XAxis(int i) { return Axes[ImAxis_X1 + i]; } 1086 | inline const ImPlotAxis& XAxis(int i) const { return Axes[ImAxis_X1 + i]; } 1087 | inline ImPlotAxis& YAxis(int i) { return Axes[ImAxis_Y1 + i]; } 1088 | inline const ImPlotAxis& YAxis(int i) const { return Axes[ImAxis_Y1 + i]; } 1089 | 1090 | inline int EnabledAxesX() { 1091 | int cnt = 0; 1092 | for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) 1093 | cnt += XAxis(i).Enabled; 1094 | return cnt; 1095 | } 1096 | 1097 | inline int EnabledAxesY() { 1098 | int cnt = 0; 1099 | for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) 1100 | cnt += YAxis(i).Enabled; 1101 | return cnt; 1102 | } 1103 | 1104 | inline void SetAxisLabel(ImPlotAxis& axis, const char* label) { 1105 | if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) { 1106 | axis.LabelOffset = TextBuffer.size(); 1107 | TextBuffer.append(label, label + strlen(label) + 1); 1108 | } 1109 | else { 1110 | axis.LabelOffset = -1; 1111 | } 1112 | } 1113 | 1114 | inline const char* GetAxisLabel(const ImPlotAxis& axis) const { return TextBuffer.Buf.Data + axis.LabelOffset; } 1115 | }; 1116 | 1117 | // Holds subplot data that must persist after EndSubplot 1118 | struct ImPlotSubplot { 1119 | ImGuiID ID; 1120 | ImPlotSubplotFlags Flags; 1121 | ImPlotSubplotFlags PreviousFlags; 1122 | ImPlotItemGroup Items; 1123 | int Rows; 1124 | int Cols; 1125 | int CurrentIdx; 1126 | ImRect FrameRect; 1127 | ImRect GridRect; 1128 | ImVec2 CellSize; 1129 | ImVector RowAlignmentData; 1130 | ImVector ColAlignmentData; 1131 | ImVector RowRatios; 1132 | ImVector ColRatios; 1133 | ImVector RowLinkData; 1134 | ImVector ColLinkData; 1135 | float TempSizes[2]; 1136 | bool FrameHovered; 1137 | bool HasTitle; 1138 | 1139 | ImPlotSubplot() { 1140 | ID = 0; 1141 | Flags = PreviousFlags = ImPlotSubplotFlags_None; 1142 | Rows = Cols = CurrentIdx = 0; 1143 | Items.Legend.Location = ImPlotLocation_North; 1144 | Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside; 1145 | Items.Legend.CanGoInside = false; 1146 | TempSizes[0] = TempSizes[1] = 0; 1147 | FrameHovered = false; 1148 | HasTitle = false; 1149 | } 1150 | }; 1151 | 1152 | // Temporary data storage for upcoming plot 1153 | struct ImPlotNextPlotData 1154 | { 1155 | ImPlotCond RangeCond[ImAxis_COUNT]; 1156 | ImPlotRange Range[ImAxis_COUNT]; 1157 | bool HasRange[ImAxis_COUNT]; 1158 | bool Fit[ImAxis_COUNT]; 1159 | double* LinkedMin[ImAxis_COUNT]; 1160 | double* LinkedMax[ImAxis_COUNT]; 1161 | 1162 | ImPlotNextPlotData() { Reset(); } 1163 | 1164 | void Reset() { 1165 | for (int i = 0; i < ImAxis_COUNT; ++i) { 1166 | HasRange[i] = false; 1167 | Fit[i] = false; 1168 | LinkedMin[i] = LinkedMax[i] = nullptr; 1169 | } 1170 | } 1171 | 1172 | }; 1173 | 1174 | // Temporary data storage for upcoming item 1175 | struct ImPlotNextItemData { 1176 | ImVec4 Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar 1177 | float LineWeight; 1178 | ImPlotMarker Marker; 1179 | float MarkerSize; 1180 | float MarkerWeight; 1181 | float FillAlpha; 1182 | float ErrorBarSize; 1183 | float ErrorBarWeight; 1184 | float DigitalBitHeight; 1185 | float DigitalBitGap; 1186 | bool RenderLine; 1187 | bool RenderFill; 1188 | bool RenderMarkerLine; 1189 | bool RenderMarkerFill; 1190 | bool HasHidden; 1191 | bool Hidden; 1192 | ImPlotCond HiddenCond; 1193 | ImPlotNextItemData() { Reset(); } 1194 | void Reset() { 1195 | for (int i = 0; i < 5; ++i) 1196 | Colors[i] = IMPLOT_AUTO_COL; 1197 | LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO; 1198 | Marker = IMPLOT_AUTO; 1199 | HasHidden = Hidden = false; 1200 | } 1201 | }; 1202 | 1203 | // Holds state information that must persist between calls to BeginPlot()/EndPlot() 1204 | struct ImPlotContext { 1205 | // Plot States 1206 | ImPool Plots; 1207 | ImPool Subplots; 1208 | ImPlotPlot* CurrentPlot; 1209 | ImPlotSubplot* CurrentSubplot; 1210 | ImPlotItemGroup* CurrentItems; 1211 | ImPlotItem* CurrentItem; 1212 | ImPlotItem* PreviousItem; 1213 | 1214 | // Tick Marks and Labels 1215 | ImPlotTicker CTicker; 1216 | 1217 | // Annotation and Tabs 1218 | ImPlotAnnotationCollection Annotations; 1219 | ImPlotTagCollection Tags; 1220 | 1221 | // Style and Colormaps 1222 | ImPlotStyle Style; 1223 | ImVector ColorModifiers; 1224 | ImVector StyleModifiers; 1225 | ImPlotColormapData ColormapData; 1226 | ImVector ColormapModifiers; 1227 | 1228 | // Time 1229 | tm Tm; 1230 | 1231 | // Temp data for general use 1232 | ImVector TempDouble1, TempDouble2; 1233 | ImVector TempInt1; 1234 | 1235 | // Misc 1236 | int DigitalPlotItemCnt; 1237 | int DigitalPlotOffset; 1238 | ImPlotNextPlotData NextPlotData; 1239 | ImPlotNextItemData NextItemData; 1240 | ImPlotInputMap InputMap; 1241 | bool OpenContextThisFrame; 1242 | ImGuiTextBuffer MousePosStringBuilder; 1243 | ImPlotItemGroup* SortItems; 1244 | 1245 | // Align plots 1246 | ImPool AlignmentData; 1247 | ImPlotAlignmentData* CurrentAlignmentH; 1248 | ImPlotAlignmentData* CurrentAlignmentV; 1249 | }; 1250 | 1251 | //----------------------------------------------------------------------------- 1252 | // [SECTION] Internal API 1253 | // No guarantee of forward compatibility here! 1254 | //----------------------------------------------------------------------------- 1255 | 1256 | namespace ImPlot { 1257 | 1258 | //----------------------------------------------------------------------------- 1259 | // [SECTION] Context Utils 1260 | //----------------------------------------------------------------------------- 1261 | 1262 | // Initializes an ImPlotContext 1263 | IMPLOT_API void Initialize(ImPlotContext* ctx); 1264 | // Resets an ImPlot context for the next call to BeginPlot 1265 | IMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx); 1266 | // Resets an ImPlot context for the next call to BeginAlignedPlots 1267 | IMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx); 1268 | // Resets an ImPlot context for the next call to BeginSubplot 1269 | IMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx); 1270 | 1271 | //----------------------------------------------------------------------------- 1272 | // [SECTION] Plot Utils 1273 | //----------------------------------------------------------------------------- 1274 | 1275 | // Gets a plot from the current ImPlotContext 1276 | IMPLOT_API ImPlotPlot* GetPlot(const char* title); 1277 | // Gets the current plot from the current ImPlotContext 1278 | IMPLOT_API ImPlotPlot* GetCurrentPlot(); 1279 | // Busts the cache for every plot in the current context 1280 | IMPLOT_API void BustPlotCache(); 1281 | 1282 | // Shows a plot's context menu. 1283 | IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot); 1284 | 1285 | //----------------------------------------------------------------------------- 1286 | // [SECTION] Setup Utils 1287 | //----------------------------------------------------------------------------- 1288 | 1289 | // Lock Setup and call SetupFinish if necessary. 1290 | static inline void SetupLock() { 1291 | ImPlotContext& gp = *GImPlot; 1292 | if (!gp.CurrentPlot->SetupLocked) 1293 | SetupFinish(); 1294 | gp.CurrentPlot->SetupLocked = true; 1295 | } 1296 | 1297 | //----------------------------------------------------------------------------- 1298 | // [SECTION] Subplot Utils 1299 | //----------------------------------------------------------------------------- 1300 | 1301 | // Advances to next subplot 1302 | IMPLOT_API void SubplotNextCell(); 1303 | 1304 | // Shows a subplot's context menu. 1305 | IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot); 1306 | 1307 | //----------------------------------------------------------------------------- 1308 | // [SECTION] Item Utils 1309 | //----------------------------------------------------------------------------- 1310 | 1311 | // Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect. 1312 | IMPLOT_API bool BeginItem(const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO); 1313 | 1314 | // Same as above but with fitting functionality. 1315 | template 1316 | bool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO) { 1317 | if (BeginItem(label_id, flags, recolor_from)) { 1318 | ImPlotPlot& plot = *GetCurrentPlot(); 1319 | if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit)) 1320 | fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]); 1321 | return true; 1322 | } 1323 | return false; 1324 | } 1325 | 1326 | // Ends an item (call only if BeginItem returns true). Pops PlotClipRect. 1327 | IMPLOT_API void EndItem(); 1328 | 1329 | // Register or get an existing item from the current plot. 1330 | IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr); 1331 | // Get a plot item from the current plot. 1332 | IMPLOT_API ImPlotItem* GetItem(const char* label_id); 1333 | // Gets the current item. 1334 | IMPLOT_API ImPlotItem* GetCurrentItem(); 1335 | // Busts the cache for every item for every plot in the current context. 1336 | IMPLOT_API void BustItemCache(); 1337 | 1338 | //----------------------------------------------------------------------------- 1339 | // [SECTION] Axis Utils 1340 | //----------------------------------------------------------------------------- 1341 | 1342 | // Returns true if any enabled axis is locked from user input. 1343 | static inline bool AnyAxesInputLocked(ImPlotAxis* axes, int count) { 1344 | for (int i = 0; i < count; ++i) { 1345 | if (axes[i].Enabled && axes[i].IsInputLocked()) 1346 | return true; 1347 | } 1348 | return false; 1349 | } 1350 | 1351 | // Returns true if all enabled axes are locked from user input. 1352 | static inline bool AllAxesInputLocked(ImPlotAxis* axes, int count) { 1353 | for (int i = 0; i < count; ++i) { 1354 | if (axes[i].Enabled && !axes[i].IsInputLocked()) 1355 | return false; 1356 | } 1357 | return true; 1358 | } 1359 | 1360 | static inline bool AnyAxesHeld(ImPlotAxis* axes, int count) { 1361 | for (int i = 0; i < count; ++i) { 1362 | if (axes[i].Enabled && axes[i].Held) 1363 | return true; 1364 | } 1365 | return false; 1366 | } 1367 | 1368 | static inline bool AnyAxesHovered(ImPlotAxis* axes, int count) { 1369 | for (int i = 0; i < count; ++i) { 1370 | if (axes[i].Enabled && axes[i].Hovered) 1371 | return true; 1372 | } 1373 | return false; 1374 | } 1375 | 1376 | // Returns true if the user has requested data to be fit. 1377 | static inline bool FitThisFrame() { 1378 | return GImPlot->CurrentPlot->FitThisFrame; 1379 | } 1380 | 1381 | // Extends the current plot's axes so that it encompasses a vertical line at x 1382 | static inline void FitPointX(double x) { 1383 | ImPlotPlot& plot = *GetCurrentPlot(); 1384 | ImPlotAxis& x_axis = plot.Axes[plot.CurrentX]; 1385 | x_axis.ExtendFit(x); 1386 | } 1387 | 1388 | // Extends the current plot's axes so that it encompasses a horizontal line at y 1389 | static inline void FitPointY(double y) { 1390 | ImPlotPlot& plot = *GetCurrentPlot(); 1391 | ImPlotAxis& y_axis = plot.Axes[plot.CurrentY]; 1392 | y_axis.ExtendFit(y); 1393 | } 1394 | 1395 | // Extends the current plot's axes so that it encompasses point p 1396 | static inline void FitPoint(const ImPlotPoint& p) { 1397 | ImPlotPlot& plot = *GetCurrentPlot(); 1398 | ImPlotAxis& x_axis = plot.Axes[plot.CurrentX]; 1399 | ImPlotAxis& y_axis = plot.Axes[plot.CurrentY]; 1400 | x_axis.ExtendFitWith(y_axis, p.x, p.y); 1401 | y_axis.ExtendFitWith(x_axis, p.y, p.x); 1402 | } 1403 | 1404 | // Returns true if two ranges overlap 1405 | static inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2) 1406 | { return r1.Min <= r2.Max && r2.Min <= r1.Max; } 1407 | 1408 | // Shows an axis's context menu. 1409 | IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false); 1410 | 1411 | //----------------------------------------------------------------------------- 1412 | // [SECTION] Legend Utils 1413 | //----------------------------------------------------------------------------- 1414 | 1415 | // Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount. 1416 | IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0)); 1417 | // Calculates the bounding box size of a legend _before_ clipping. 1418 | IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical); 1419 | // Clips calculated legend size 1420 | IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad); 1421 | // Renders legend entries into a bounding box 1422 | IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList); 1423 | // Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window! This is not thoroughly tested nor scrollable!). 1424 | IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true); 1425 | // Shows a legend's context menu. 1426 | IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible); 1427 | 1428 | //----------------------------------------------------------------------------- 1429 | // [SECTION] Label Utils 1430 | //----------------------------------------------------------------------------- 1431 | 1432 | // Create a a string label for a an axis value 1433 | IMPLOT_API void LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round = false); 1434 | 1435 | //----------------------------------------------------------------------------- 1436 | // [SECTION] Styling Utils 1437 | //----------------------------------------------------------------------------- 1438 | 1439 | // Get styling data for next item (call between Begin/EndItem) 1440 | static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; } 1441 | 1442 | // Returns true if a color is set to be automatically determined 1443 | static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; } 1444 | // Returns true if a style color is set to be automatically determined 1445 | static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); } 1446 | // Returns the automatically deduced style color 1447 | IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx); 1448 | 1449 | // Returns the style color whether it is automatic or custom set 1450 | static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; } 1451 | static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); } 1452 | 1453 | // Draws vertical text. The position is the bottom left of the text rect. 1454 | IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr); 1455 | // Draws multiline horizontal text centered. 1456 | IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr); 1457 | // Calculates the size of vertical text 1458 | static inline ImVec2 CalcTextSizeVertical(const char *text) { 1459 | ImVec2 sz = ImGui::CalcTextSize(text); 1460 | return ImVec2(sz.y, sz.x); 1461 | } 1462 | // Returns white or black text given background color 1463 | static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; } 1464 | static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); } 1465 | // Lightens or darkens a color for hover 1466 | static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); } 1467 | 1468 | // Clamps a label position so that it fits a rect defined by Min/Max 1469 | static inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) { 1470 | if (pos.x < Min.x) pos.x = Min.x; 1471 | if (pos.y < Min.y) pos.y = Min.y; 1472 | if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x; 1473 | if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y; 1474 | return pos; 1475 | } 1476 | 1477 | // Returns a color from the Color map given an index >= 0 (modulo will be performed). 1478 | IMPLOT_API ImU32 GetColormapColorU32(int idx, ImPlotColormap cmap); 1479 | // Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired. 1480 | IMPLOT_API ImU32 NextColormapColorU32(); 1481 | // Linearly interpolates a color from the current colormap given t between 0 and 1. 1482 | IMPLOT_API ImU32 SampleColormapU32(float t, ImPlotColormap cmap); 1483 | 1484 | // Render a colormap bar 1485 | IMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous); 1486 | 1487 | //----------------------------------------------------------------------------- 1488 | // [SECTION] Math and Misc Utils 1489 | //----------------------------------------------------------------------------- 1490 | 1491 | // Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2) 1492 | IMPLOT_API double NiceNum(double x, bool round); 1493 | // Computes order of magnitude of double. 1494 | static inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); } 1495 | // Returns the precision required for a order of magnitude. 1496 | static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; } 1497 | // Returns a floating point precision to use given a value 1498 | static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); } 1499 | // Round a value to a given precision 1500 | static inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; } 1501 | 1502 | // Returns the intersection point of two lines A and B (assumes they are not parallel!) 1503 | static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) { 1504 | float v1 = (a1.x * a2.y - a1.y * a2.x); float v2 = (b1.x * b2.y - b1.y * b2.x); 1505 | float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x)); 1506 | return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3); 1507 | } 1508 | 1509 | // Fills a buffer with n samples linear interpolated from vmin to vmax 1510 | template 1511 | void FillRange(ImVector& buffer, int n, T vmin, T vmax) { 1512 | buffer.resize(n); 1513 | T step = (vmax - vmin) / (n - 1); 1514 | for (int i = 0; i < n; ++i) { 1515 | buffer[i] = vmin + i * step; 1516 | } 1517 | } 1518 | 1519 | // Calculate histogram bin counts and widths 1520 | template 1521 | static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) { 1522 | switch (meth) { 1523 | case ImPlotBin_Sqrt: 1524 | bins_out = (int)ceil(sqrt(count)); 1525 | break; 1526 | case ImPlotBin_Sturges: 1527 | bins_out = (int)ceil(1.0 + log2(count)); 1528 | break; 1529 | case ImPlotBin_Rice: 1530 | bins_out = (int)ceil(2 * cbrt(count)); 1531 | break; 1532 | case ImPlotBin_Scott: 1533 | width_out = 3.49 * ImStdDev(values, count) / cbrt(count); 1534 | bins_out = (int)round(range.Size() / width_out); 1535 | break; 1536 | } 1537 | width_out = range.Size() / bins_out; 1538 | } 1539 | 1540 | //----------------------------------------------------------------------------- 1541 | // Time Utils 1542 | //----------------------------------------------------------------------------- 1543 | 1544 | // Returns true if year is leap year (366 days long) 1545 | static inline bool IsLeapYear(int year) { 1546 | return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 1547 | } 1548 | // Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed. 1549 | static inline int GetDaysInMonth(int year, int month) { 1550 | static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 1551 | return days[month] + (int)(month == 1 && IsLeapYear(year)); 1552 | } 1553 | 1554 | // Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone). 1555 | IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm); 1556 | // Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp. 1557 | IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm); 1558 | 1559 | // Make a UNIX timestamp from a tm struct expressed in local time. 1560 | IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm); 1561 | // Make a tm struct expressed in local time from a UNIX timestamp. 1562 | IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm); 1563 | 1564 | // NB: The following functions only work if there is a current ImPlotContext because the 1565 | // internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime. 1566 | 1567 | // Make a timestamp from time components. 1568 | // year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999] 1569 | IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0); 1570 | // Get year component from timestamp [1970-3000] 1571 | IMPLOT_API int GetYear(const ImPlotTime& t); 1572 | 1573 | // Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract. 1574 | IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count); 1575 | // Rounds a timestamp down to nearest unit. 1576 | IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit); 1577 | // Rounds a timestamp up to the nearest unit. 1578 | IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit); 1579 | // Rounds a timestamp up or down to the nearest unit. 1580 | IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit); 1581 | // Combines the date of one timestamp with the time-of-day of another timestamp. 1582 | IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part); 1583 | 1584 | // Formats the time part of timestamp t into a buffer according to #fmt 1585 | IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk); 1586 | // Formats the date part of timestamp t into a buffer according to #fmt 1587 | IMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601); 1588 | // Formats the time and/or date parts of a timestamp t into a buffer according to #fmt 1589 | IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeSpec fmt); 1590 | 1591 | // Shows a date picker widget block (year/month/day). 1592 | // #level = 0 for day, 1 for month, 2 for year. Modified by user interaction. 1593 | // #t will be set when a day is clicked and the function will return true. 1594 | // #t1 and #t2 are optional dates to highlight. 1595 | IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr); 1596 | // Shows a time picker widget block (hour/min/sec). 1597 | // #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true. 1598 | IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t); 1599 | 1600 | //----------------------------------------------------------------------------- 1601 | // [SECTION] Transforms 1602 | //----------------------------------------------------------------------------- 1603 | 1604 | static inline double TransformForward_Log10(double v, void*) { 1605 | v = v <= 0.0 ? DBL_MIN : v; 1606 | return ImLog10(v); 1607 | } 1608 | 1609 | static inline double TransformInverse_Log10(double v, void*) { 1610 | return ImPow(10, v); 1611 | } 1612 | 1613 | static inline double TransformForward_SymLog(double v, void*) { 1614 | return 2.0 * ImAsinh(v / 2.0); 1615 | } 1616 | 1617 | static inline double TransformInverse_SymLog(double v, void*) { 1618 | return 2.0 * ImSinh(v / 2.0); 1619 | } 1620 | 1621 | static inline double TransformForward_Logit(double v, void*) { 1622 | v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON); 1623 | return ImLog10(v / (1 - v)); 1624 | } 1625 | 1626 | static inline double TransformInverse_Logit(double v, void*) { 1627 | return 1.0 / (1.0 + ImPow(10,-v)); 1628 | } 1629 | 1630 | //----------------------------------------------------------------------------- 1631 | // [SECTION] Formatters 1632 | //----------------------------------------------------------------------------- 1633 | 1634 | static inline int Formatter_Default(double value, char* buff, int size, void* data) { 1635 | char* fmt = (char*)data; 1636 | return ImFormatString(buff, size, fmt, value); 1637 | } 1638 | 1639 | static inline int Formatter_Logit(double value, char* buff, int size, void*) { 1640 | if (value == 0.5) 1641 | return ImFormatString(buff,size,"1/2"); 1642 | else if (value < 0.5) 1643 | return ImFormatString(buff,size,"%g", value); 1644 | else 1645 | return ImFormatString(buff,size,"1 - %g", 1 - value); 1646 | } 1647 | 1648 | struct Formatter_Time_Data { 1649 | ImPlotTime Time; 1650 | ImPlotDateTimeSpec Spec; 1651 | ImPlotFormatter UserFormatter; 1652 | void* UserFormatterData; 1653 | }; 1654 | 1655 | static inline int Formatter_Time(double, char* buff, int size, void* data) { 1656 | Formatter_Time_Data* ftd = (Formatter_Time_Data*)data; 1657 | return FormatDateTime(ftd->Time, buff, size, ftd->Spec); 1658 | } 1659 | 1660 | //------------------------------------------------------------------------------ 1661 | // [SECTION] Locator 1662 | //------------------------------------------------------------------------------ 1663 | 1664 | void Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); 1665 | void Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); 1666 | void Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); 1667 | void Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); 1668 | 1669 | } // namespace ImPlot 1670 | --------------------------------------------------------------------------------