Update to ImGui v1.91.6

Update ImPlot
Fix misc compilation errors
This commit is contained in:
Arnaud Jamin
2025-01-06 14:23:18 -05:00
parent 9a1cd48434
commit 934ef438f8
27 changed files with 13108 additions and 5518 deletions
@@ -21,7 +21,7 @@ private:
EAssetTypeCategories::Type AssetCategory;
};
IMPLEMENT_MODULE(FCogDebugEditorModule, CogEditor);
IMPLEMENT_MODULE(FCogDebugEditorModule, CogDebugEditor);
//----------------------------------------------------------------------------------------------------------------------
void FCogDebugEditorModule::StartupModule()
@@ -954,12 +954,8 @@ bool FCogEngineWindow_Inspector::HasPropertyAnyChildren(const FProperty* Propert
{
if (const FStructProperty* StructProperty = CastField<FStructProperty>(Property))
{
for (TFieldIterator<FProperty> It(StructProperty->Struct); It; ++It)
{
return true;
}
return false;
const TFieldIterator<FProperty> It(StructProperty->Struct);
return It ? true : false;
}
else if (const FArrayProperty* ArrayProperty = CastField<FArrayProperty>(Property))
{
@@ -5,6 +5,8 @@
#include "CogWindowConsoleCommandManager.h"
#include "CogWindowManager.h"
#include "CogWindowWidgets.h"
#include "Engine/EngineBaseTypes.h"
#include "Engine/World.h"
#include "imgui.h"
#include "imgui_internal.h"
#include "Misc/CoreMisc.h"
@@ -80,10 +80,9 @@ void FCogImguiContext::Initialize()
ImGuiIO& IO = ImGui::GetIO();
IO.UserData = this;
IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
IO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
IO.ConfigFlags |= ImGuiConfigFlags_NavNoCaptureKeyboard;
IO.ConfigFlags |= ImGuiConfigFlags_NavEnableSetMousePos;
IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
IO.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
@@ -38,7 +38,7 @@ float FCogImguiHelper::GetNextItemWidth()
{
float Width;
const ImGuiContext& g = *GImGui;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
{
Width = g.NextItemData.Width;
}
@@ -75,7 +75,7 @@ int32 SCogImguiWidget::OnPaint(
TArray VerticesSlice(Vertices.GetData() + DrawCmd.VtxOffset, Vertices.Num() - DrawCmd.VtxOffset);
TArray IndicesSlice(Indices.GetData() + DrawCmd.IdxOffset, DrawCmd.ElemCount);
UTexture2D* Texture = DrawCmd.GetTexID();
UTexture2D* Texture = Cast<UTexture2D>(DrawCmd.GetTexID());
if (TextureBrush.GetResourceObject() != Texture)
{
TextureBrush.SetResourceObject(Texture);
@@ -217,7 +217,7 @@ void UCogWindowManager::Render(float DeltaTime)
FCogImGuiContextScope ImGuiContextScope(Context);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingInCentralNode | ImGuiDockNodeFlags_AutoHideTabBar);
ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode | ImGuiDockNodeFlags_AutoHideTabBar);
ImGui::PopStyleColor(1);
@@ -83,7 +83,7 @@ void FCogWindow_Settings::RenderContent()
if (ShortcutWidth > 0.0f)
{
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - ShortcutWidth);
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - ShortcutWidth);
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
ImGui::Text("%s", ShortcutText.Get());
ImGui::PopStyleColor();
@@ -4,6 +4,8 @@
#include "imgui.h"
#include "UObject/ReflectedTypeAccessors.h"
#include <Templates/SubclassOf.h>
class AActor;
class APawn;
class FEnumProperty;
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2024 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+27 -14
View File
@@ -21,20 +21,20 @@
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
@@ -42,20 +42,30 @@
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience
//#define IMGUI_INCLUDE_IMGUI_USER_H
//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
//#define IMGUI_USE_LEGACY_CRC32_ADLER
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
@@ -76,10 +86,13 @@
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
// Only works in combination with IMGUI_ENABLE_FREETYPE.
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
//---- Use stb_truetype to build and rasterize the font atlas (default)
@@ -98,7 +111,7 @@
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- ...Or use Dear ImGui's own very basic math operators.
#define IMGUI_DEFINE_MATH_OPERATORS
//#define IMGUI_DEFINE_MATH_OPERATORS
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+139 -107
View File
@@ -2,8 +2,11 @@
// This is a slightly modified version of stb_textedit.h 1.14.
// Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
// - Added name to struct or it may be forward declared in our code.
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
// Grep for [DEAR IMGUI] to find the changes.
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
// stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools
@@ -30,7 +33,7 @@
// DEPENDENCIES
//
// Uses the C runtime function 'memmove', which you can override
// by defining STB_TEXTEDIT_memmove before the implementation.
// by defining IMSTB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations.
//
//
@@ -40,7 +43,7 @@
// 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
// 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
// 1.9 (2016-08-27) customizable move-by-word
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
@@ -208,6 +211,7 @@
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
//
// Each of these functions potentially updates the string and updates the
// state.
@@ -242,7 +246,12 @@
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
// anything other type you wante before including.
// anything other type you want before including.
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
// transformed into text and stb_textedit_text() is automatically called.
//
// text: [DEAR IMGUI] added 2024-09
// call this to text inputs sent to the textfield.
//
//
// When rendering, you can read the cursor position and selection state from
@@ -274,8 +283,8 @@
////
////
#ifndef INCLUDE_STB_TEXTEDIT_H
#define INCLUDE_STB_TEXTEDIT_H
#ifndef INCLUDE_IMSTB_TEXTEDIT_H
#define INCLUDE_IMSTB_TEXTEDIT_H
////////////////////////////////////////////////////////////////////////
//
@@ -286,38 +295,38 @@
// and undo state.
//
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#endif
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#endif
#ifndef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE int
#ifndef IMSTB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_CHARTYPE int
#endif
#ifndef STB_TEXTEDIT_POSITIONTYPE
#define STB_TEXTEDIT_POSITIONTYPE int
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE
#define IMSTB_TEXTEDIT_POSITIONTYPE int
#endif
typedef struct
{
// private data
STB_TEXTEDIT_POSITIONTYPE where;
STB_TEXTEDIT_POSITIONTYPE insert_length;
STB_TEXTEDIT_POSITIONTYPE delete_length;
IMSTB_TEXTEDIT_POSITIONTYPE where;
IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage;
} StbUndoRecord;
typedef struct
{
// private data
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point;
int undo_char_point, redo_char_point;
} StbUndoState;
typedef struct
typedef struct STB_TexteditState
{
/////////////////////
//
@@ -371,7 +380,7 @@ typedef struct
float ymin,ymax; // height of row above and below baseline
int num_chars;
} StbTexteditRow;
#endif //INCLUDE_STB_TEXTEDIT_H
#endif //INCLUDE_IMSTB_TEXTEDIT_H
////////////////////////////////////////////////////////////////////////////
@@ -384,11 +393,11 @@ typedef struct
// implementation isn't include-guarded, since it might have indirectly
// included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
#ifndef STB_TEXTEDIT_memmove
#ifndef IMSTB_TEXTEDIT_memmove
#include <string.h>
#define STB_TEXTEDIT_memmove memmove
#define IMSTB_TEXTEDIT_memmove memmove
#endif
@@ -398,7 +407,7 @@ typedef struct
//
// traverse the layout to locate the nearest character to a display position
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
{
StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str);
@@ -437,13 +446,13 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
if (x < r.x1) {
// search characters in row for one that straddles 'x'
prev_x = r.x0;
for (k=0; k < r.num_chars; ++k) {
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
if (x < prev_x+w) {
if (x < prev_x+w/2)
return k+i;
else
return k+i+1;
return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k);
}
prev_x += w;
}
@@ -458,7 +467,7 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
}
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
// goes off the top or bottom of the text
@@ -476,7 +485,7 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
}
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
int p = 0;
@@ -502,11 +511,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
//
// forward declarations
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
typedef struct
{
@@ -518,7 +527,7 @@ typedef struct
// find the x/y location of a character, and remember info about the previous row in
// case we get a move-up event (for page up, we'll have to rescan)
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
{
StbTexteditRow r;
int prev_start = 0;
@@ -549,7 +558,10 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
i += r.num_chars;
find->y += r.baseline_y_delta;
if (i == z) // [DEAR IMGUI]
{
r.num_chars = 0; // [DEAR IMGUI]
break; // [DEAR IMGUI]
}
}
find->first_char = first = i;
@@ -559,14 +571,14 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
// now scan to find xpos
find->x = r.x0;
for (i=0; first+i < n; ++i)
for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first)
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
}
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
// make the selection/cursor state valid if client altered the string
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) {
@@ -580,7 +592,7 @@ static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
}
// delete characters while updating undo
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
{
stb_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, where, len);
@@ -588,7 +600,7 @@ static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *sta
}
// delete the section
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(state)) {
@@ -625,7 +637,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
}
// move cursor to last character of selection
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state);
@@ -636,14 +648,25 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
}
}
// [DEAR IMGUI]
// Functions must be implemented for UTF8 support
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
#endif
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
#endif
#ifdef STB_TEXTEDIT_IS_SPACE
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
{
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
}
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
{
--c; // always move at least one character
while( c >= 0 && !is_word_boundary( str, c ) )
@@ -658,7 +681,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
#endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
{
const int len = STB_TEXTEDIT_STRINGLEN(str);
++c; // always move at least one character
@@ -685,7 +708,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
}
// API cut: delete selection
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicitly clamps
@@ -696,7 +719,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
}
// API paste: replace existing selection with passed-in text
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
{
// if there's a selection, the paste should delete it
stb_textedit_clamp(str, state);
@@ -716,36 +739,44 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
#define STB_TEXTEDIT_KEYTYPE int
#endif
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
{
// can't add newline in single-line mode
if (text[0] == '\n' && state->single_line)
return;
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
state->cursor += text_len;
state->has_preferred_x = 0;
}
}
else {
stb_textedit_delete_selection(str, state); // implicitly clamps
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
stb_text_makeundo_insert(state, state->cursor, text_len);
state->cursor += text_len;
state->has_preferred_x = 0;
}
}
}
// API key: process a keyboard input
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
{
retry:
switch (key) {
default: {
#ifdef STB_TEXTEDIT_KEYTOTEXT
int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) {
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
// can't add newline in single-line mode
if (c == '\n' && state->single_line)
break;
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
++state->cursor;
state->has_preferred_x = 0;
}
} else {
stb_textedit_delete_selection(str,state); // implicitly clamps
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
stb_text_makeundo_insert(state, state->cursor, 1);
++state->cursor;
state->has_preferred_x = 0;
}
}
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
stb_textedit_text(str, state, &ch, 1);
}
#endif
break;
}
@@ -771,7 +802,7 @@ retry:
stb_textedit_move_to_first(state);
else
if (state->cursor > 0)
--state->cursor;
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
state->has_preferred_x = 0;
break;
@@ -780,7 +811,7 @@ retry:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str, state);
else
++state->cursor;
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
stb_textedit_clamp(str, state);
state->has_preferred_x = 0;
break;
@@ -790,7 +821,7 @@ retry:
stb_textedit_prep_selection_at_cursor(state);
// move selection left
if (state->select_end > 0)
--state->select_end;
state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end);
state->cursor = state->select_end;
state->has_preferred_x = 0;
break;
@@ -840,7 +871,7 @@ retry:
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
// move selection right
++state->select_end;
state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end);
stb_textedit_clamp(str, state);
state->cursor = state->select_end;
state->has_preferred_x = 0;
@@ -889,14 +920,14 @@ retry:
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
if (x > goal_x)
break;
++state->cursor;
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
}
stb_textedit_clamp(str, state);
@@ -951,14 +982,14 @@ retry:
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
if (x > goal_x)
break;
++state->cursor;
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
}
stb_textedit_clamp(str, state);
@@ -986,7 +1017,7 @@ retry:
else {
int n = STB_TEXTEDIT_STRINGLEN(str);
if (state->cursor < n)
stb_textedit_delete(str, state, state->cursor, 1);
stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor);
}
state->has_preferred_x = 0;
break;
@@ -998,8 +1029,9 @@ retry:
else {
stb_textedit_clamp(str, state);
if (state->cursor > 0) {
stb_textedit_delete(str, state, state->cursor-1, 1);
--state->cursor;
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
stb_textedit_delete(str, state, prev, state->cursor - prev);
state->cursor = prev;
}
}
state->has_preferred_x = 0;
@@ -1109,8 +1141,8 @@ retry:
static void stb_textedit_flush_redo(StbUndoState *state)
{
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
}
// discard the oldest entry in the undo list
@@ -1122,13 +1154,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records
state->undo_char_point -= n;
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
}
--state->undo_point;
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
}
}
@@ -1138,7 +1170,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
// fill up even though the undo buffer didn't
static void stb_textedit_discard_redo(StbUndoState *state)
{
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
if (state->redo_point <= k) {
// if the k'th undo state has characters, clean those up
@@ -1146,7 +1178,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i;
// move the remaining redo character data to the end of the buffer
state->redo_char_point += n;
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
// adjust the position of all the other records to account for above memmove
for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0)
@@ -1154,12 +1186,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
}
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// [DEAR IMGUI]
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
// now move redo_point to point to the new one
++state->redo_point;
@@ -1173,32 +1205,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
// if we have no free records, we have to make room, by sliding the
// existing records down
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state);
// if the characters to store won't possibly fit in the buffer, we can't undo
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
state->undo_point = 0;
state->undo_char_point = 0;
return NULL;
}
// if we don't have enough free characters in the buffer, we have to make room
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++];
}
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
{
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL)
return NULL;
r->where = pos;
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) {
r->char_storage = -1;
@@ -1210,7 +1242,7 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
}
}
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord u, *r;
@@ -1237,7 +1269,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// characters stored for *undoing* don't leave room for redo
// if the last is true, we have to bail
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
// the undo records take up too much character space; there's no space to store the redo characters
r->insert_length = 0;
} else {
@@ -1246,7 +1278,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// there's definitely room to store the characters eventually
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
// should never happen:
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return;
// there's currently not enough room, so discard a redo record
stb_textedit_discard_redo(s);
@@ -1278,11 +1310,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
s->redo_point--;
}
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord *u, r;
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return;
// we need to do two things: apply the redo record, and create an undo record
@@ -1334,20 +1366,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
stb_text_createundo(&state->undostate, where, 0, length);
}
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
if (p) {
for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
}
}
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
if (p) {
for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
@@ -1359,8 +1391,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
{
state->undostate.undo_point = 0;
state->undostate.undo_char_point = 0;
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0;
state->cursor = 0;
state->has_preferred_x = 0;
@@ -1383,16 +1415,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
{
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
}
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif//STB_TEXTEDIT_IMPLEMENTATION
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION
/*
------------------------------------------------------------------------------
+1 -1
View File
@@ -656,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph,
// codepoints without a glyph received the font's "missing character" glyph,
// typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
+1 -1
View File
@@ -155,7 +155,7 @@ A: Maybe. Check the demo, gallery, or Announcements ([2020](https://github.com/e
**Q: Does ImPlot support 3D plots?**
A: No, and likely never will since ImGui only deals in 2D rendering.
A: An experimental extension to ImPlot, [ImPlot3D](https://github.com/brenocq/implot3d), provides a similar API for plotting and interacting with 3D data.
**Q: Does ImPlot provide analytic tools?**
+1 -1
View File
@@ -15,7 +15,6 @@ The list below represents a combination of high-priority work, nice-to-have feat
- add `PlotBubbles` (see MATLAB bubble chart)
- add non-zero references for `PlotBars` etc.
- add exploding to `PlotPieChart` (on hover-highlight?)
- fix appearance of `PlotBars` spacing
## Styling
@@ -80,6 +79,7 @@ Ideally every `PlotX` function should use our faster rendering pipeline when it
|PlotDummy|-|-|-|-|
## Completed
- add exploding to `PlotPieChart` (on legend hover)
- make BeginPlot take fewer args:
- make query a tool -> `DragRect`
- rework DragLine/Point to use ButtonBehavior
+66 -69
View File
@@ -31,7 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
You can read releases logs https://github.com/epezent/implot/releases for more details.
- 2023/08/20 (0.17) - ImPlotFlags_NoChild was removed as child windows are no longer needed to capture scroll. You can safely remove this flag if you were using it.
- 2023/08/20 (0.17) - ImPlotFlags_NoChild was removed as child windows are no longer needed to capture scroll. You can safely remove this flag if you were using it.
- 2023/06/26 (0.15) - Various build fixes related to updates in Dear ImGui internals.
- 2022/11/25 (0.15) - Make PlotText honor ImPlotItemFlags_NoFit.
- 2022/06/19 (0.14) - The signature of ColormapScale has changed to accommodate a new ImPlotColormapScaleFlags parameter
@@ -125,8 +125,11 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
*/
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "implot.h"
#ifndef IMGUI_DISABLE
#include "implot_internal.h"
#include <stdlib.h>
@@ -293,35 +296,35 @@ struct ImPlotStyleVarInfo {
static const ImPlotStyleVarInfo GPlotStyleVarInfo[] =
{
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight
{ ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight
{ ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize
};
static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) {
@@ -341,8 +344,8 @@ void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *te
ImGuiContext& g = *GImGui;
ImFont* font = g.Font;
// Align to be pixel perfect
pos.x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y);
pos.x = ImFloor(pos.x);
pos.y = ImFloor(pos.y);
const float scale = g.FontSize / font->FontSize;
const char* s = text_begin;
int chars_exp = (int)(text_end - s);
@@ -604,10 +607,10 @@ bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2
if (legend_rect.Max.y > outer_rect_pad.Max.y) {
legend_rect.Max.y = outer_rect_pad.Max.y;
clamped = true;
}
}
return clamped;
}
int LegendSortingComp(const void* _a, const void* _b) {
ImPlotItemGroup* items = GImPlot->SortItems;
const int a = *(const int*)_a;
@@ -947,20 +950,6 @@ tm* GetLocTime(const ImPlotTime& t, tm* ptm) {
#endif
}
inline ImPlotTime MkTime(struct tm *ptm) {
if (GetStyle().UseLocalTime)
return MkLocTime(ptm);
else
return MkGmtTime(ptm);
}
inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
if (GetStyle().UseLocalTime)
return GetLocTime(t,ptm);
else
return GetGmtTime(t,ptm);
}
ImPlotTime MakeTime(int year, int month, int day, int hour, int min, int sec, int us) {
tm& Tm = GImPlot->Tm;
@@ -990,6 +979,12 @@ int GetYear(const ImPlotTime& t) {
return Tm.tm_year + 1900;
}
int GetMonth(const ImPlotTime& t) {
tm& Tm = GImPlot->Tm;
ImPlot::GetTime(t, &Tm);
return Tm.tm_mon;
}
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
tm& Tm = GImPlot->Tm;
ImPlotTime t_out = t;
@@ -1982,9 +1977,9 @@ bool UpdateInput(ImPlotPlot& plot) {
if (any_hov && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) {
float zoom_rate = gp.InputMap.ZoomRate;
if (IO.MouseWheel == 0.0f)
zoom_rate = 0;
else if (IO.MouseWheel > 0)
if (IO.MouseWheel == 0.0f)
zoom_rate = 0;
else if (IO.MouseWheel > 0)
zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));
ImVec2 rect_size = plot.PlotRect.GetSize();
float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f);
@@ -2451,7 +2446,7 @@ bool BeginPlot(const char* title_id, const ImVec2& size, ImPlotFlags flags) {
ResetCtxForNextPlot(GImPlot);
return false;
}
// setup items (or dont)
if (gp.CurrentItems == nullptr)
gp.CurrentItems = &plot.Items;
@@ -2778,7 +2773,7 @@ void EndPlot() {
// FINAL RENDER -----------------------------------------------------------
const bool render_border = gp.Style.PlotBorderSize > 0 && gp.Style.Colors[ImPlotCol_PlotBorder].w > 0;
const bool render_border = gp.Style.PlotBorderSize > 0 && GetStyleColorVec4(ImPlotCol_PlotBorder).w > 0;
const bool any_x_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);
const bool any_y_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);
@@ -3047,7 +3042,7 @@ void EndPlot() {
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,
legend_out ? plot.FrameRect : plot.PlotRect,
legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding
);
);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
@@ -3058,7 +3053,7 @@ void EndPlot() {
ImGui::KeepAliveID(plot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, plot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (ImGui::IsWindowHovered() && legend.RectClamped.Contains(IO.MousePos));
if (legend_scrollable) {
if (legend.Hovered) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID);
@@ -3069,10 +3064,10 @@ void EndPlot() {
legend.Scroll.x += scroll_step * IO.MouseWheel;
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
@@ -3082,18 +3077,18 @@ void EndPlot() {
}
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
bool legend_contextable = ShowLegendEntries(plot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
// main ctx menu
if (gp.OpenContextThisFrame && legend_contextable && !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus))
ImGui::OpenPopup("##LegendContext");
ImGui::OpenPopup("##LegendContext");
if (ImGui::BeginPopup("##LegendContext")) {
ImGui::Text("Legend"); ImGui::Separator();
if (ShowLegendContextMenu(legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend)))
@@ -3566,7 +3561,7 @@ void EndSubplots() {
const ImVec2 legend_pos = GetLocationPos(subplot.FrameRect, legend_size, legend.Location, gp.Style.PlotPadding);
legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
legend.RectClamped = legend.Rect;
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,subplot.FrameRect, gp.Style.PlotPadding);
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,subplot.FrameRect, gp.Style.PlotPadding);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
@@ -3577,7 +3572,7 @@ void EndSubplots() {
ImGui::KeepAliveID(subplot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, subplot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (subplot.FrameHovered && legend.RectClamped.Contains(ImGui::GetIO().MousePos));
if (legend_scrollable) {
if (legend.Hovered) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID);
@@ -3588,10 +3583,10 @@ void EndSubplots() {
legend.Scroll.x += scroll_step * IO.MouseWheel;
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
@@ -3602,13 +3597,13 @@ void EndSubplots() {
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
bool legend_contextable = ShowLegendEntries(subplot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
if (legend_contextable && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoMenus) && ImGui::GetIO().MouseReleased[gp.InputMap.Menu])
ImGui::OpenPopup("##LegendContext");
if (ImGui::BeginPopup("##LegendContext")) {
@@ -5171,7 +5166,7 @@ void ShowUserGuide() {
ImGui::Indent();
ImGui::BulletText("Left-click drag on axis labels to pan an individual axis.");
ImGui::Unindent();
ImGui::BulletText("Scroll in the plot area to zoom both X any Y axes.");
ImGui::BulletText("Scroll in the plot area to zoom both X and Y axes.");
ImGui::Indent();
ImGui::BulletText("Scroll on axis labels to zoom an individual axis.");
ImGui::Unindent();
@@ -5883,3 +5878,5 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
#endif
} // namespace ImPlot
#endif // #ifndef IMGUI_DISABLE
+10 -5
View File
@@ -46,6 +46,7 @@
#pragma once
#include "imgui.h"
#ifndef IMGUI_DISABLE
//-----------------------------------------------------------------------------
// [SECTION] Macros and Defines
@@ -56,7 +57,7 @@
// backward nor forward ABI compatibility and also function call overhead. If you
// do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellanous section).
#ifndef IMPLOT_API
#define IMPLOT_API __declspec( dllexport )
#define IMPLOT_API
#endif
// ImPlot version string.
@@ -286,8 +287,10 @@ enum ImPlotInfLinesFlags_ {
// Flags for PlotPieChart
enum ImPlotPieChartFlags_ {
ImPlotPieChartFlags_None = 0, // default
ImPlotPieChartFlags_Normalize = 1 << 10 // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
ImPlotPieChartFlags_None = 0, // default
ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
ImPlotPieChartFlags_IgnoreHidden = 1 << 11, // ignore hidden slices when drawing the pie chart (as if they were not there)
ImPlotPieChartFlags_Exploding = 1 << 12 // Explode legend-hovered slice
};
// Flags for PlotHeatmap
@@ -828,7 +831,7 @@ IMPLOT_API void SetNextAxesToFit();
// an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a slight performance
// cost, but probably not enough to worry about unless your data is very large. Examples:
//
// ImPlotPoint MyDataGetter(void* data, int idx) {
// ImPlotPoint MyDataGetter(int idx, void* data) {
// MyData* my_data = (MyData*)data;
// ImPlotPoint p;
// p.x = my_data->GetTime(idx);
@@ -892,6 +895,7 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
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);
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);
// 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.
@@ -1292,4 +1296,5 @@ IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id,
} // namespace ImPlot
#endif
#endif // #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
#endif // #ifndef IMGUI_DISABLE
+18 -8
View File
@@ -28,6 +28,7 @@
#endif
#include "implot.h"
#ifndef IMGUI_DISABLE
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,6 +44,8 @@
#define CHECKBOX_FLAG(flags, flag) ImGui::CheckboxFlags(#flag, (unsigned int*)&flags, flag)
#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
// Encapsulates examples for customizing ImPlot.
namespace MyImPlot {
@@ -610,10 +613,9 @@ void Demo_PieCharts() {
static ImPlotPieChartFlags flags = 0;
ImGui::SetNextItemWidth(250);
ImGui::DragFloat4("Values", data1, 0.01f, 0, 1);
if ((data1[0] + data1[1] + data1[2] + data1[3]) < 1) {
ImGui::SameLine();
CHECKBOX_FLAG(flags,ImPlotPieChartFlags_Normalize);
}
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Normalize);
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_IgnoreHidden);
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Exploding);
if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
@@ -1388,7 +1390,7 @@ void Demo_LegendOptions() {
static int num_dummy_items = 25;
ImGui::SliderInt("Num Dummy Items (Demo Scrolling)", &num_dummy_items, 0, 100);
if (ImPlot::BeginPlot("##Legend",ImVec2(-1,0))) {
ImPlot::SetupLegend(loc, flags);
static MyImPlot::WaveData data1(0.001, 0.2, 4, 0.2);
@@ -1407,11 +1409,11 @@ void Demo_LegendOptions() {
char label[16];
snprintf(label, sizeof(label), "Item %03d", i+4);
ImPlot::PlotDummy(label);
}
}
ImPlot::EndPlot();
}
}
}
//-----------------------------------------------------------------------------
void Demo_DragPoints() {
@@ -2479,3 +2481,11 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
}
} // namespace MyImplot
#else
void ImPlot::ShowDemoWindow(bool* p_open) {}
#endif
#endif // #ifndef IMGUI_DISABLE
+24 -4
View File
@@ -31,13 +31,13 @@
#pragma once
#include <time.h>
#include "imgui_internal.h"
#ifndef IMPLOT_VERSION
#error Must include implot.h before implot_internal.h
#endif
#ifndef IMGUI_DISABLE
#include <time.h>
#include "imgui_internal.h"
// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()
#if (IMGUI_VERSION_NUM < 18303)
@@ -1417,7 +1417,7 @@ IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_s
// Calculates the bounding box size of a legend _before_ clipping.
IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
// Clips calculated legend size
IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
// Renders legend entries into a bounding box
IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
// 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!).
@@ -1564,11 +1564,24 @@ IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
// NB: The following functions only work if there is a current ImPlotContext because the
// internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.
// // Make a UNIX timestamp from a tm struct according to the current ImPlotStyle.UseLocalTime setting.
static inline ImPlotTime MkTime(struct tm *ptm) {
if (GetStyle().UseLocalTime) return MkLocTime(ptm);
else return MkGmtTime(ptm);
}
// Get a tm struct from a UNIX timestamp according to the current ImPlotStyle.UseLocalTime setting.
static inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
if (GetStyle().UseLocalTime) return GetLocTime(t,ptm);
else return GetGmtTime(t,ptm);
}
// Make a timestamp from time components.
// year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]
IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
// Get year component from timestamp [1970-3000]
IMPLOT_API int GetYear(const ImPlotTime& t);
// Get month component from timestamp [0-11]
IMPLOT_API int GetMonth(const ImPlotTime& t);
// Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.
IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
@@ -1581,6 +1594,11 @@ IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
// Combines the date of one timestamp with the time-of-day of another timestamp.
IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
// Get the current time as a timestamp.
static inline ImPlotTime Now() { return ImPlotTime::FromDouble((double)time(nullptr)); }
// Get the current date as a timestamp.
static inline ImPlotTime Today() { return ImPlot::FloorTime(Now(), ImPlotTimeUnit_Day); }
// Formats the time part of timestamp t into a buffer according to #fmt
IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);
// Formats the date part of timestamp t into a buffer according to #fmt
@@ -1667,3 +1685,5 @@ void Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels,
void Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
} // namespace ImPlot
#endif // #ifndef IMGUI_DISABLE
+147 -43
View File
@@ -22,8 +22,11 @@
// ImPlot v0.17
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "implot.h"
#ifndef IMGUI_DISABLE
#include "implot_internal.h"
//-----------------------------------------------------------------------------
@@ -2197,76 +2200,175 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
// [SECTION] PlotPieChart
//-----------------------------------------------------------------------------
IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) {
IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col, bool detached = false) {
const float resolution = 50 / (2 * IM_PI);
ImVec2 buffer[52];
buffer[0] = PlotToPixels(center,IMPLOT_AUTO,IMPLOT_AUTO);
int n = ImMax(3, (int)((a1 - a0) * resolution));
double da = (a1 - a0) / (n - 1);
int i = 0;
for (; i < n; ++i) {
double a = a0 + i * da;
buffer[i + 1] = PlotToPixels(center.x + radius * cos(a), center.y + radius * sin(a),IMPLOT_AUTO,IMPLOT_AUTO);
if (detached) {
const double offset = 0.08; // Offset of the detached slice
const double width_scale = 0.95; // Scale factor for the width of the detached slice
double a_mid = (a0 + a1) / 2;
double new_a0 = a_mid - (a1 - a0) * width_scale / 2;
double new_a1 = a_mid + (a1 - a0) * width_scale / 2;
double new_da = (new_a1 - new_a0) / (n - 1);
ImPlotPoint offsetCenter(center.x + offset * cos(a_mid), center.y + offset * sin(a_mid));
// Start point (center of the offset)
buffer[0] = PlotToPixels(offsetCenter, IMPLOT_AUTO, IMPLOT_AUTO);
for (; i < n; ++i) {
double a = new_a0 + i * new_da;
buffer[i + 1] = PlotToPixels(
offsetCenter.x + (radius + offset/2) * cos(a),
offsetCenter.y + (radius + offset/2) * sin(a),
IMPLOT_AUTO, IMPLOT_AUTO
);
}
} else {
buffer[0] = PlotToPixels(center, IMPLOT_AUTO, IMPLOT_AUTO);
for (; i < n; ++i) {
double a = a0 + i * da;
buffer[i + 1] = PlotToPixels(
center.x + radius * cos(a),
center.y + radius * sin(a),
IMPLOT_AUTO, IMPLOT_AUTO);
}
}
buffer[i+1] = buffer[0];
// Close the shape
buffer[i + 1] = buffer[0];
// fill
draw_list.AddConvexPolyFilled(buffer, n + 1, col);
draw_list.AddConvexPolyFilled(buffer, n + 2, col);
// border (for AA)
draw_list.AddPolyline(buffer, n + 2, col, 0, 2.0f);
}
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & draw_list = *GetPlotDrawList();
double PieChartSum(const T* values, int count, bool ignore_hidden) {
double sum = 0;
for (int i = 0; i < count; ++i)
sum += (double)values[i];
const bool normalize = ImHasFlag(flags,ImPlotPieChartFlags_Normalize) || sum > 1.0;
ImPlotPoint center(x,y);
PushPlotClipRect();
if (ignore_hidden) {
ImPlotContext& gp = *GImPlot;
ImPlotItemGroup& Items = *gp.CurrentItems;
for (int i = 0; i < count; ++i) {
if (i >= Items.GetItemCount())
break;
ImPlotItem* item = Items.GetItemByIndex(i);
IM_ASSERT(item != nullptr);
if (item->Show) {
sum += (double)values[i];
}
}
}
else {
for (int i = 0; i < count; ++i) {
sum += (double)values[i];
}
}
return sum;
}
template <typename T>
void PlotPieChartEx(const char* const label_ids[], const T* values, int count, ImPlotPoint center, double radius, double angle0, ImPlotPieChartFlags flags) {
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
double a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0;
ImPlotPoint Pmin = ImPlotPoint(x-radius,y-radius);
ImPlotPoint Pmax = ImPlotPoint(x+radius,y+radius);
ImPlotPoint Pmin = ImPlotPoint(center.x - radius, center.y - radius);
ImPlotPoint Pmax = ImPlotPoint(center.x + radius, center.y + radius);
for (int i = 0; i < count; ++i) {
double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
if (BeginItemEx(label_ids[i], FitterRect(Pmin,Pmax))) {
ImU32 col = GetCurrentItem()->Color;
if (percent < 0.5) {
RenderPieSlice(draw_list, center, radius, a0, a1, col);
}
else {
RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
ImPlotItem* item = GetItem(label_ids[i]);
const double percent = normalize ? (double)values[i] / sum : (double)values[i];
const bool skip = sum <= 0.0 || (ignore_hidden && item != nullptr && !item->Show);
if (!skip)
a1 = a0 + 2 * IM_PI * percent;
if (BeginItemEx(label_ids[i], FitterRect(Pmin, Pmax))) {
const bool hovered = ImPlot::IsLegendEntryHovered(label_ids[i]) && ImHasFlag(flags, ImPlotPieChartFlags_Exploding);
if (sum > 0.0) {
ImU32 col = GetCurrentItem()->Color;
if (percent < 0.5) {
RenderPieSlice(draw_list, center, radius, a0, a1, col, hovered);
}
else {
RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col, hovered);
RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col, hovered);
}
}
EndItem();
}
a0 = a1;
if (!skip)
a0 = a1;
}
}
int PieChartFormatter(double value, char* buff, int size, void* data) {
const char* fmt = (const char*)data;
return snprintf(buff, size, fmt, value);
};
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
PlotPieChart<T>(label_ids, values, count, x, y, radius, PieChartFormatter, (void*)fmt, angle0, flags);
}
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
ImPlotPoint center(x, y);
PushPlotClipRect();
PlotPieChartEx(label_ids, values, count, center, radius, angle0, flags);
if (fmt != nullptr) {
a0 = angle0 * 2 * IM_PI / 360.0;
a1 = angle0 * 2 * IM_PI / 360.0;
double a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32];
for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]);
double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
if (item->Show) {
ImFormatString(buffer, 32, fmt, (double)values[i]);
ImVec2 size = ImGui::CalcTextSize(buffer);
double angle = a0 + (a1 - a0) * 0.5;
ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle),IMPLOT_AUTO,IMPLOT_AUTO);
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
draw_list.AddText(pos - size * 0.5f, col, buffer);
IM_ASSERT(item != nullptr);
const double percent = normalize ? (double)values[i] / sum : (double)values[i];
const bool skip = ignore_hidden && item != nullptr && !item->Show;
if (!skip) {
a1 = a0 + 2 * IM_PI * percent;
if (item->Show) {
fmt((double)values[i], buffer, 32, fmt_data);
ImVec2 size = ImGui::CalcTextSize(buffer);
double angle = a0 + (a1 - a0) * 0.5;
const bool hovered = ImPlot::IsLegendEntryHovered(label_ids[i]) && ImHasFlag(flags, ImPlotPieChartFlags_Exploding);
const double offset = (hovered ? 0.6 : 0.5) * radius;
ImVec2 pos = PlotToPixels(center.x + offset * cos(angle), center.y + offset * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO);
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
draw_list.AddText(pos - size * 0.5f, col, buffer);
}
a0 = a1;
}
a0 = a1;
}
}
PopPlotClipRect();
}
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO
@@ -2327,8 +2429,8 @@ struct GetterHeatmapColMaj {
{ }
template <typename I> IMPLOT_INLINE RectC operator()(I idx) const {
double val = (double)Values[idx];
const int r = idx % Cols;
const int c = idx / Cols;
const int r = idx % Rows;
const int c = idx / Rows;
const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));
RectC rect;
rect.Pos = p;
@@ -2742,3 +2844,5 @@ void PlotDummy(const char* label_id, ImPlotDummyFlags flags) {
}
} // namespace ImPlot
#endif // #ifndef IMGUI_DISABLE