|
@@ -2,7 +2,7 @@
|
|
|
// Main code & documentation
|
|
// Main code & documentation
|
|
|
|
|
|
|
|
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
|
|
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
|
|
|
-// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
|
|
|
|
|
|
|
+// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
|
|
|
// Get latest version at https://github.com/ocornut/imgui
|
|
// Get latest version at https://github.com/ocornut/imgui
|
|
|
// Releases change-log at https://github.com/ocornut/imgui/releases
|
|
// Releases change-log at https://github.com/ocornut/imgui/releases
|
|
|
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
|
|
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
|
|
@@ -76,18 +76,20 @@
|
|
|
- read the FAQ below this section!
|
|
- read the FAQ below this section!
|
|
|
- your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
|
|
- your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
|
|
|
- call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
|
|
- call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
|
|
|
- - see examples/ folder for standalone sample applications. e.g. examples/opengl_example/
|
|
|
|
|
|
|
+ - see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first at it is the simplest.
|
|
|
- customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
|
|
- customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
|
|
|
|
|
|
|
|
- getting started:
|
|
- getting started:
|
|
|
- - initialisation: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the 'Settings' data.
|
|
|
|
|
|
|
+ - init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'.
|
|
|
|
|
+ - init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory.
|
|
|
- every frame:
|
|
- every frame:
|
|
|
- 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the 'Input' data, then call ImGui::NewFrame().
|
|
|
|
|
- 2/ use any ImGui function you want between NewFrame() and Render()
|
|
|
|
|
- 3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
|
|
|
|
|
|
|
+ 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input'
|
|
|
|
|
+ 2/ call ImGui::NewFrame().
|
|
|
|
|
+ 3/ use any ImGui function you want between NewFrame() and Render()
|
|
|
|
|
+ 4/ call ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
|
|
|
- all rendering information are stored into command-lists until ImGui::Render() is called.
|
|
- all rendering information are stored into command-lists until ImGui::Render() is called.
|
|
|
- ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
|
|
- ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
|
|
|
- - effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
|
|
|
|
|
|
|
+ - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases.
|
|
|
- refer to the examples applications in the examples/ folder for instruction on how to setup your code.
|
|
- refer to the examples applications in the examples/ folder for instruction on how to setup your code.
|
|
|
- a typical application skeleton may be:
|
|
- a typical application skeleton may be:
|
|
|
|
|
|
|
@@ -100,32 +102,34 @@
|
|
|
// TODO: Fill others settings of the io structure
|
|
// TODO: Fill others settings of the io structure
|
|
|
|
|
|
|
|
// Load texture atlas
|
|
// Load texture atlas
|
|
|
|
|
+ // There is a default font so you don't need to care about choosing a font yet
|
|
|
unsigned char* pixels;
|
|
unsigned char* pixels;
|
|
|
- int width, height, bytes_per_pixels;
|
|
|
|
|
- io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height, &bytes_per_pixels);
|
|
|
|
|
- // TODO: copy texture to graphics memory.
|
|
|
|
|
- // TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
|
|
|
|
|
|
|
+ int width, height;
|
|
|
|
|
+ io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);
|
|
|
|
|
+ // TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system
|
|
|
|
|
+ // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'
|
|
|
|
|
|
|
|
// Application main loop
|
|
// Application main loop
|
|
|
while (true)
|
|
while (true)
|
|
|
{
|
|
{
|
|
|
- // 1) get low-level input
|
|
|
|
|
- // e.g. on Win32, GetKeyboardState(), or poll your events, etc.
|
|
|
|
|
-
|
|
|
|
|
- // 2) TODO: fill all fields of IO structure and call NewFrame
|
|
|
|
|
|
|
+ // 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.)
|
|
|
|
|
+ // TODO: fill all fields of IO structure and call NewFrame
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
io.DeltaTime = 1.0f/60.0f;
|
|
io.DeltaTime = 1.0f/60.0f;
|
|
|
io.MousePos = mouse_pos;
|
|
io.MousePos = mouse_pos;
|
|
|
io.MouseDown[0] = mouse_button_0;
|
|
io.MouseDown[0] = mouse_button_0;
|
|
|
|
|
+ io.MouseDown[1] = mouse_button_1;
|
|
|
io.KeysDown[i] = ...
|
|
io.KeysDown[i] = ...
|
|
|
|
|
+
|
|
|
|
|
+ // 2) call NewFrame(), after this point you can use ImGui::* functions anytime
|
|
|
ImGui::NewFrame();
|
|
ImGui::NewFrame();
|
|
|
|
|
|
|
|
- // 3) most of your application code here - you can use any of ImGui::* functions at any point in the frame
|
|
|
|
|
|
|
+ // 3) most of your application code here
|
|
|
ImGui::Begin("My window");
|
|
ImGui::Begin("My window");
|
|
|
ImGui::Text("Hello, world.");
|
|
ImGui::Text("Hello, world.");
|
|
|
ImGui::End();
|
|
ImGui::End();
|
|
|
- GameUpdate();
|
|
|
|
|
- GameRender();
|
|
|
|
|
|
|
+ MyGameUpdate(); // may use ImGui functions
|
|
|
|
|
+ MyGameRender(); // may use ImGui functions
|
|
|
|
|
|
|
|
// 4) render & swap video buffers
|
|
// 4) render & swap video buffers
|
|
|
ImGui::Render();
|
|
ImGui::Render();
|
|
@@ -410,6 +414,7 @@
|
|
|
- window: get size/pos helpers given names (see discussion in #249)
|
|
- window: get size/pos helpers given names (see discussion in #249)
|
|
|
- window: a collapsed window can be stuck behind the main menu bar?
|
|
- window: a collapsed window can be stuck behind the main menu bar?
|
|
|
- window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
|
|
- window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
|
|
|
|
|
+ - window: consider renaming "GetWindowFont" which conflict with old Windows #define (#340)
|
|
|
- window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
|
|
- window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
|
|
|
- draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
|
|
- draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
|
|
|
!- scrolling: allow immediately effective change of scroll if we haven't appended items yet
|
|
!- scrolling: allow immediately effective change of scroll if we haven't appended items yet
|
|
@@ -439,6 +444,8 @@
|
|
|
- columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
|
|
- columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
|
|
|
- columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
|
|
- columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
|
|
|
- columns: user specify columns size (#125)
|
|
- columns: user specify columns size (#125)
|
|
|
|
|
+ - columns: flag to add horizontal separator above/below?
|
|
|
|
|
+ - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
|
|
|
- combo: sparse combo boxes (via function call?)
|
|
- combo: sparse combo boxes (via function call?)
|
|
|
- combo: contents should extends to fit label if combo widget is small
|
|
- combo: contents should extends to fit label if combo widget is small
|
|
|
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
|
|
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
|
|
@@ -475,12 +482,14 @@
|
|
|
- tree node / optimization: avoid formatting when clipped.
|
|
- tree node / optimization: avoid formatting when clipped.
|
|
|
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
|
|
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
|
|
|
- tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
|
|
- tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
|
|
|
|
|
+ - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
|
|
|
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
|
|
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
|
|
|
- settings: write more decent code to allow saving/loading new fields
|
|
- settings: write more decent code to allow saving/loading new fields
|
|
|
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
|
|
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
|
|
|
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
|
|
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
|
|
|
- style: color-box not always square?
|
|
- style: color-box not always square?
|
|
|
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
|
|
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
|
|
|
|
|
+ - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
|
|
|
- text: simple markup language for color change?
|
|
- text: simple markup language for color change?
|
|
|
- font: helper to add glyph redirect/replacements (e.g. redirect alternate apostrophe unicode code points to ascii one, etc.)
|
|
- font: helper to add glyph redirect/replacements (e.g. redirect alternate apostrophe unicode code points to ascii one, etc.)
|
|
|
- log: LogButtons() options for specifying depth and/or hiding depth slider
|
|
- log: LogButtons() options for specifying depth and/or hiding depth slider
|
|
@@ -1597,7 +1606,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
|
|
|
{
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
g.ActiveId = id;
|
|
g.ActiveId = id;
|
|
|
- g.ActiveIdAllowHoveringOthers = false;
|
|
|
|
|
|
|
+ g.ActiveIdAllowOverlap = false;
|
|
|
g.ActiveIdIsJustActivated = true;
|
|
g.ActiveIdIsJustActivated = true;
|
|
|
g.ActiveIdWindow = window;
|
|
g.ActiveIdWindow = window;
|
|
|
}
|
|
}
|
|
@@ -1606,7 +1615,7 @@ void ImGui::SetHoveredID(ImGuiID id)
|
|
|
{
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
g.HoveredId = id;
|
|
g.HoveredId = id;
|
|
|
- g.HoveredIdAllowHoveringOthers = false;
|
|
|
|
|
|
|
+ g.HoveredIdAllowOverlap = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ImGui::KeepAliveID(ImGuiID id)
|
|
void ImGui::KeepAliveID(ImGuiID id)
|
|
@@ -1667,7 +1676,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
|
|
|
window->DC.LastItemHoveredRect = true;
|
|
window->DC.LastItemHoveredRect = true;
|
|
|
window->DC.LastItemHoveredAndUsable = false;
|
|
window->DC.LastItemHoveredAndUsable = false;
|
|
|
if (g.HoveredRootWindow == window->RootWindow)
|
|
if (g.HoveredRootWindow == window->RootWindow)
|
|
|
- if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowHoveringOthers || (g.ActiveId == window->MoveID))
|
|
|
|
|
|
|
+ if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveID))
|
|
|
if (IsWindowContentHoverable(window))
|
|
if (IsWindowContentHoverable(window))
|
|
|
window->DC.LastItemHoveredAndUsable = true;
|
|
window->DC.LastItemHoveredAndUsable = true;
|
|
|
}
|
|
}
|
|
@@ -1696,11 +1705,11 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when
|
|
|
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
|
|
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
|
|
|
{
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
- if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowHoveringOthers)
|
|
|
|
|
|
|
+ if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap)
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindowRead();
|
|
ImGuiWindow* window = GetCurrentWindowRead();
|
|
|
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
|
|
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
|
|
|
- if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowHoveringOthers) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
|
|
|
|
|
|
|
+ if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
|
|
|
if (IsWindowContentHoverable(g.HoveredRootWindow))
|
|
if (IsWindowContentHoverable(g.HoveredRootWindow))
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -1848,11 +1857,11 @@ void ImGui::NewFrame()
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
|
|
|
|
|
// Check user data
|
|
// Check user data
|
|
|
- IM_ASSERT(g.IO.DeltaTime >= 0.0f);
|
|
|
|
|
|
|
+ IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues)
|
|
|
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
|
|
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
|
|
|
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
|
|
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
|
|
|
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
|
|
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
|
|
|
- IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid
|
|
|
|
|
|
|
+ IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting
|
|
|
|
|
|
|
|
if (!g.Initialized)
|
|
if (!g.Initialized)
|
|
|
{
|
|
{
|
|
@@ -1928,7 +1937,7 @@ void ImGui::NewFrame()
|
|
|
// Clear reference to active widget if the widget isn't alive anymore
|
|
// Clear reference to active widget if the widget isn't alive anymore
|
|
|
g.HoveredIdPreviousFrame = g.HoveredId;
|
|
g.HoveredIdPreviousFrame = g.HoveredId;
|
|
|
g.HoveredId = 0;
|
|
g.HoveredId = 0;
|
|
|
- g.HoveredIdAllowHoveringOthers = false;
|
|
|
|
|
|
|
+ g.HoveredIdAllowOverlap = false;
|
|
|
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
|
|
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
|
|
|
SetActiveID(0);
|
|
SetActiveID(0);
|
|
|
g.ActiveIdPreviousFrame = g.ActiveId;
|
|
g.ActiveIdPreviousFrame = g.ActiveId;
|
|
@@ -1982,6 +1991,7 @@ void ImGui::NewFrame()
|
|
|
g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
|
|
g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
|
|
|
g.MouseCursor = ImGuiMouseCursor_Arrow;
|
|
g.MouseCursor = ImGuiMouseCursor_Arrow;
|
|
|
g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
|
|
g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
|
|
|
|
|
+ g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
|
|
|
|
|
|
|
|
// If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
|
|
// If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
|
|
|
if (mouse_owned_by_application)
|
|
if (mouse_owned_by_application)
|
|
@@ -2269,8 +2279,7 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDr
|
|
|
// If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
|
|
// If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
|
|
|
const unsigned long long int max_vtx_idx = (unsigned long long int)1L << (sizeof(ImDrawIdx)*8);
|
|
const unsigned long long int max_vtx_idx = (unsigned long long int)1L << (sizeof(ImDrawIdx)*8);
|
|
|
(void)max_vtx_idx;
|
|
(void)max_vtx_idx;
|
|
|
- IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx);
|
|
|
|
|
- (void)max_vtx_idx;
|
|
|
|
|
|
|
+ IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx); // Too many vertices in same ImDrawList
|
|
|
|
|
|
|
|
GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
|
|
GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
|
|
|
GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
|
|
GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
|
|
@@ -2331,8 +2340,15 @@ void ImGui::EndFrame()
|
|
|
ImGui::EndTooltip();
|
|
ImGui::EndTooltip();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
|
|
|
|
|
+ if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)
|
|
|
|
|
+ {
|
|
|
|
|
+ g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);
|
|
|
|
|
+ g.OsImePosSet = g.OsImePosRequest;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Hide implicit "Debug" window if it hasn't been used
|
|
// Hide implicit "Debug" window if it hasn't been used
|
|
|
- IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End
|
|
|
|
|
|
|
+ IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls
|
|
|
if (g.CurrentWindow && !g.CurrentWindow->Accessed)
|
|
if (g.CurrentWindow && !g.CurrentWindow->Accessed)
|
|
|
g.CurrentWindow->Active = false;
|
|
g.CurrentWindow->Active = false;
|
|
|
ImGui::End();
|
|
ImGui::End();
|
|
@@ -2368,9 +2384,8 @@ void ImGui::EndFrame()
|
|
|
for (int i = 0; i != g.Windows.Size; i++)
|
|
for (int i = 0; i != g.Windows.Size; i++)
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = g.Windows[i];
|
|
ImGuiWindow* window = g.Windows[i];
|
|
|
- if (window->Flags & ImGuiWindowFlags_ChildWindow) // if a child is active its parent will add it
|
|
|
|
|
- if (window->Active)
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
|
|
|
|
|
+ continue;
|
|
|
AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
|
|
AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
|
|
|
}
|
|
}
|
|
|
IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
|
|
IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
|
|
@@ -2602,6 +2617,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
|
|
|
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align, const ImVec2* clip_min, const ImVec2* clip_max)
|
|
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align, const ImVec2* clip_min, const ImVec2* clip_max)
|
|
|
{
|
|
{
|
|
|
// Hide anything after a '##' string
|
|
// Hide anything after a '##' string
|
|
@@ -3011,6 +3027,16 @@ bool ImGui::IsItemVisible()
|
|
|
return r.Overlaps(window->DC.LastItemRect);
|
|
return r.Overlaps(window->DC.LastItemRect);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
|
|
|
|
|
+void ImGui::SetItemAllowOverlap()
|
|
|
|
|
+{
|
|
|
|
|
+ ImGuiState& g = *GImGui;
|
|
|
|
|
+ if (g.HoveredId == g.CurrentWindow->DC.LastItemID)
|
|
|
|
|
+ g.HoveredIdAllowOverlap = true;
|
|
|
|
|
+ if (g.ActiveId == g.CurrentWindow->DC.LastItemID)
|
|
|
|
|
+ g.ActiveIdAllowOverlap = true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
ImVec2 ImGui::GetItemRectMin()
|
|
ImVec2 ImGui::GetItemRectMin()
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindowRead();
|
|
ImGuiWindow* window = GetCurrentWindowRead();
|
|
@@ -3069,7 +3095,7 @@ void ImGui::BeginTooltip()
|
|
|
|
|
|
|
|
void ImGui::EndTooltip()
|
|
void ImGui::EndTooltip()
|
|
|
{
|
|
{
|
|
|
- IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
|
|
|
|
|
|
|
+ IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls
|
|
|
ImGui::End();
|
|
ImGui::End();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3238,7 +3264,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e
|
|
|
void ImGui::EndPopup()
|
|
void ImGui::EndPopup()
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
- IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
|
|
|
|
|
|
|
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
|
|
|
IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);
|
|
IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);
|
|
|
ImGui::End();
|
|
ImGui::End();
|
|
|
if (!(window->Flags & ImGuiWindowFlags_Modal))
|
|
if (!(window->Flags & ImGuiWindowFlags_Modal))
|
|
@@ -3316,7 +3342,7 @@ void ImGui::EndChild()
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
|
|
|
|
|
- IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
|
|
|
|
|
|
|
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
|
|
|
if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
|
|
if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
|
|
|
{
|
|
{
|
|
|
ImGui::End();
|
|
ImGui::End();
|
|
@@ -4261,7 +4287,7 @@ float ImGui::CalcItemWidth()
|
|
|
static void SetCurrentFont(ImFont* font)
|
|
static void SetCurrentFont(ImFont* font)
|
|
|
{
|
|
{
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
- IM_ASSERT(font && font->IsLoaded());
|
|
|
|
|
|
|
+ IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
|
|
|
IM_ASSERT(font->Scale > 0.0f);
|
|
IM_ASSERT(font->Scale > 0.0f);
|
|
|
g.Font = font;
|
|
g.Font = font;
|
|
|
g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
|
|
g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
|
|
@@ -5533,6 +5559,7 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
|
|
|
return opened;
|
|
return opened;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// FIXME: Split into CollapsingHeader(label, default_open?) and TreeNodeBehavior(label), obsolete the 4 parameters function.
|
|
|
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
|
|
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
@@ -5541,6 +5568,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
|
|
|
|
|
|
|
|
ImGuiState& g = *GImGui;
|
|
ImGuiState& g = *GImGui;
|
|
|
const ImGuiStyle& style = g.Style;
|
|
const ImGuiStyle& style = g.Style;
|
|
|
|
|
+ const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
|
|
|
|
|
|
|
|
IM_ASSERT(str_id != NULL || label != NULL);
|
|
IM_ASSERT(str_id != NULL || label != NULL);
|
|
|
if (str_id == NULL)
|
|
if (str_id == NULL)
|
|
@@ -5548,27 +5576,27 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
|
|
|
if (label == NULL)
|
|
if (label == NULL)
|
|
|
label = str_id;
|
|
label = str_id;
|
|
|
const ImGuiID id = window->GetID(str_id);
|
|
const ImGuiID id = window->GetID(str_id);
|
|
|
-
|
|
|
|
|
- // Framed header expand a little outside the default padding
|
|
|
|
|
- const ImVec2 window_padding = window->WindowPadding;
|
|
|
|
|
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
- const ImVec2 pos_min = window->DC.CursorPos;
|
|
|
|
|
- const ImVec2 pos_max = window->Pos + GetContentRegionMax();
|
|
|
|
|
- ImRect bb = ImRect(pos_min, ImVec2(pos_max.x, pos_min.y + label_size.y));
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // We vertically grow up to current line height up the typical widget height.
|
|
|
|
|
+ const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y);
|
|
|
|
|
+ const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), label_size.y + padding.y*2);
|
|
|
|
|
+ ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
|
|
|
if (display_frame)
|
|
if (display_frame)
|
|
|
{
|
|
{
|
|
|
- bb.Min.x -= (float)(int)(window_padding.x*0.5f) - 1;
|
|
|
|
|
- bb.Max.x += (float)(int)(window_padding.x*0.5f) - 1;
|
|
|
|
|
- bb.Max.y += style.FramePadding.y * 2;
|
|
|
|
|
|
|
+ // Framed header expand a little outside the default padding
|
|
|
|
|
+ bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
|
|
|
|
|
+ bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const float collapser_width = g.FontSize + style.FramePadding.x*2;
|
|
|
|
|
- const ImRect text_bb(bb.Min, bb.Min + ImVec2(collapser_width + style.FramePadding.x*2*0 + (label_size.x > 0.0f ? label_size.x : 0.0f), label_size.y));
|
|
|
|
|
- ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y), display_frame ? style.FramePadding.y : 0.0f);
|
|
|
|
|
|
|
+ const float collapser_width = g.FontSize + padding.x*2;
|
|
|
|
|
+ const float text_width = collapser_width + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
|
|
|
|
|
+ ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
|
|
|
|
|
|
|
|
- const ImRect interact_bb = display_frame ? bb : ImRect(text_bb.Min, text_bb.Max + ImVec2(style.FramePadding.x*2,0.0f)); // FIXME
|
|
|
|
|
|
|
+ // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
|
|
|
|
|
+ // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not)
|
|
|
|
|
+ const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y);
|
|
|
bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
|
|
bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
|
|
|
-
|
|
|
|
|
if (!ItemAdd(interact_bb, &id))
|
|
if (!ItemAdd(interact_bb, &id))
|
|
|
return opened;
|
|
return opened;
|
|
|
|
|
|
|
@@ -5582,22 +5610,24 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
|
|
|
|
|
|
|
|
// Render
|
|
// Render
|
|
|
const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
|
|
|
+ const ImVec2 text_pos = bb.Min + padding + ImVec2(collapser_width, text_base_offset_y);
|
|
|
if (display_frame)
|
|
if (display_frame)
|
|
|
{
|
|
{
|
|
|
// Framed type
|
|
// Framed type
|
|
|
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
|
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
|
|
- RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true);
|
|
|
|
|
|
|
+ RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), opened, 1.0f, true);
|
|
|
if (g.LogEnabled)
|
|
if (g.LogEnabled)
|
|
|
{
|
|
{
|
|
|
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
|
|
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
|
|
|
const char log_prefix[] = "\n##";
|
|
const char log_prefix[] = "\n##";
|
|
|
- LogRenderedText(bb.Min + style.FramePadding, log_prefix, log_prefix+3);
|
|
|
|
|
|
|
+ const char log_suffix[] = "##";
|
|
|
|
|
+ LogRenderedText(text_pos, log_prefix, log_prefix+3);
|
|
|
|
|
+ RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
|
|
|
|
|
+ LogRenderedText(text_pos, log_suffix+1, log_suffix+3);
|
|
|
}
|
|
}
|
|
|
- RenderTextClipped(bb.Min + style.FramePadding + ImVec2(collapser_width,0), bb.Max, label, NULL, &label_size);
|
|
|
|
|
- if (g.LogEnabled)
|
|
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- const char log_suffix[] = "##";
|
|
|
|
|
- LogRenderedText(bb.Min + style.FramePadding, log_suffix, log_suffix+2);
|
|
|
|
|
|
|
+ RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
@@ -5605,10 +5635,11 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
|
|
|
// Unframed typed for tree nodes
|
|
// Unframed typed for tree nodes
|
|
|
if (hovered)
|
|
if (hovered)
|
|
|
RenderFrame(bb.Min, bb.Max, col, false);
|
|
RenderFrame(bb.Min, bb.Max, col, false);
|
|
|
- RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, g.FontSize*0.15f), opened, 0.70f, false);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false);
|
|
|
if (g.LogEnabled)
|
|
if (g.LogEnabled)
|
|
|
- LogRenderedText(bb.Min, ">");
|
|
|
|
|
- RenderText(bb.Min + ImVec2(collapser_width,0), label);
|
|
|
|
|
|
|
+ LogRenderedText(text_pos, ">");
|
|
|
|
|
+ RenderText(text_pos, label);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return opened;
|
|
return opened;
|
|
@@ -7109,7 +7140,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Edit a string of text
|
|
// Edit a string of text
|
|
|
-// FIXME: This is rather complex partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time.
|
|
|
|
|
|
|
+// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188
|
|
|
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
|
|
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
|
|
|
{
|
|
{
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
@@ -7128,7 +7159,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
|
|
const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
|
|
|
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
|
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
|
|
|
|
|
|
|
- ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
|
|
|
|
|
|
+ const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
|
|
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
|
|
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
|
|
|
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
|
|
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
|
|
|
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
|
|
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
|
|
@@ -7197,7 +7228,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
{
|
|
{
|
|
|
// Start edition
|
|
// Start edition
|
|
|
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
|
|
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
|
|
|
- // From the moment we focused we are ignoring the content of 'buf'
|
|
|
|
|
|
|
+ // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
|
|
|
const int prev_len_w = edit_state.CurLenW;
|
|
const int prev_len_w = edit_state.CurLenW;
|
|
|
edit_state.Text.resize(buf_size+1); // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
|
|
edit_state.Text.resize(buf_size+1); // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
|
|
|
edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
|
|
edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
|
|
@@ -7205,7 +7236,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
const char* buf_end = NULL;
|
|
const char* buf_end = NULL;
|
|
|
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
|
|
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
|
|
|
edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
|
|
edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
|
|
|
- edit_state.InputCursorScreenPos = ImVec2(-1.f, -1.f);
|
|
|
|
|
edit_state.CursorAnimReset();
|
|
edit_state.CursorAnimReset();
|
|
|
|
|
|
|
|
// Preserve cursor position and undo/redo stack if we come back to same widget
|
|
// Preserve cursor position and undo/redo stack if we come back to same widget
|
|
@@ -7259,8 +7289,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
edit_state.BufSizeA = buf_size;
|
|
edit_state.BufSizeA = buf_size;
|
|
|
|
|
|
|
|
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
|
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
|
|
- // Down the line we should have a cleaner concept of focused vs active in the library.
|
|
|
|
|
- g.ActiveIdAllowHoveringOthers = !io.MouseDown[0];
|
|
|
|
|
|
|
+ // Down the line we should have a cleaner library-wide concept of Selected vs Active.
|
|
|
|
|
+ g.ActiveIdAllowOverlap = !io.MouseDown[0];
|
|
|
|
|
|
|
|
// Edit in progress
|
|
// Edit in progress
|
|
|
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
|
|
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
|
|
@@ -7407,9 +7437,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
// Apply new value immediately - copy modified buffer back
|
|
// Apply new value immediately - copy modified buffer back
|
|
|
- // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
|
|
|
|
|
- // FIXME: We actually always render 'buf' when calling DrawList->AddText
|
|
|
|
|
- // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
|
|
|
|
|
|
|
+ // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
|
|
|
|
|
+ // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
|
|
|
|
|
+ // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
|
|
|
if (is_editable)
|
|
if (is_editable)
|
|
|
{
|
|
{
|
|
|
edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
|
|
edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
|
|
@@ -7624,11 +7654,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|
|
if (cursor_is_visible)
|
|
if (cursor_is_visible)
|
|
|
draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
|
|
draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
|
|
|
|
|
|
|
|
- // Notify OS of text input position for advanced IME
|
|
|
|
|
- if (is_editable && io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_screen_pos) > 0.0001f)
|
|
|
|
|
- io.ImeSetInputScreenPosFn((int)cursor_screen_pos.x - 1, (int)(cursor_screen_pos.y - g.FontSize)); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
|
|
|
|
|
-
|
|
|
|
|
- edit_state.InputCursorScreenPos = cursor_screen_pos;
|
|
|
|
|
|
|
+ // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
|
|
|
|
+ if (is_editable)
|
|
|
|
|
+ g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -8650,7 +8678,7 @@ void ImGui::EndGroup()
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
|
|
|
|
|
|
- IM_ASSERT(!window->DC.GroupStack.empty());
|
|
|
|
|
|
|
+ IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
|
|
|
|
|
|
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
|
|
|
|