Merge branch 'master' into viewport

# Conflicts:
#	imgui.cpp
This commit is contained in:
omar 2018-12-18 15:02:35 +01:00
commit 9c916cdaf9
9 changed files with 132 additions and 82 deletions

View File

@ -33,6 +33,7 @@ You may use the Issue Tracker to submit bug reports, feature requests or suggest
If you have been using dear imgui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information are useful in a given context. If you have been using dear imgui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information are useful in a given context.
## How to create an Pull Request ## How to create an Pull Request
- Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
- When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). - When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.).
- When fixing a warning or compilation problem, please post the compiler log and specify the version and OS you are using. - When fixing a warning or compilation problem, please post the compiler log and specify the version and OS you are using.
- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. You can drag pictures/files here (prefer github attachments over 3rd party hosting). - Try to attach screenshots to clarify the context and demonstrate the feature at a glance. You can drag pictures/files here (prefer github attachments over 3rd party hosting).

View File

@ -1,4 +1,5 @@
- Please read https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md - Please read https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md
- Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
- When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). - When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.).
- When adding a feature, try to attach screenshots/gifs to clarify the context and demonstrate the feature at a glance. - When adding a feature, try to attach screenshots/gifs to clarify the context and demonstrate the feature at a glance.
- When fixing a warning or compilation problem, post the compiler log and specify the version and OS you are using. - When fixing a warning or compilation problem, post the compiler log and specify the version and OS you are using.

View File

@ -50,6 +50,8 @@ Other Changes:
(It does not provide the docking/splitting/merging of windows available in the Docking branch) (It does not provide the docking/splitting/merging of windows available in the Docking branch)
- Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering - Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering
the ID, as a convenience to avoid using the ### operator. the ID, as a convenience to avoid using the ### operator.
- Window, Focus, Popup: Fixed an issue where closing a popup by clicking another window with the _NoMove flag would refocus
the parent window of the popup instead of the newly clicked window.
- Window: Contents size is preserved while a window collapsed. Fix auto-resizing window losing their size for one frame when uncollapsed. - Window: Contents size is preserved while a window collapsed. Fix auto-resizing window losing their size for one frame when uncollapsed.
- Window: Contents size is preserved while a window contents is hidden (unless it is hidden for resizing purpose). - Window: Contents size is preserved while a window contents is hidden (unless it is hidden for resizing purpose).
- Window: Resizing windows from edge is now enabled by default (io.ConfigWindowsResizeFromEdges=true). Note that - Window: Resizing windows from edge is now enabled by default (io.ConfigWindowsResizeFromEdges=true). Note that

View File

@ -3,13 +3,16 @@ dear imgui,
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) [![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui)
[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720)
_(This library is free but needs your support to sustain its development. There are many desirable features and maintenance ahead. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for technical support, custom development etc. Email: omarcornut at gmail)._ _(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_
Monthly donations via Patreon: Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) <br>&nbsp;[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)
One-off donations via PayPal: Individuals/hobbyists: support continued maintenance and development via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) <br>&nbsp;&nbsp;[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
Businesses: support continued maintenance and development via support contracts or sponsoring a few weeks/months of development:
<br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
@ -158,7 +161,7 @@ Some of the goals for 2019 are:
- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), public branch looking for feedback) - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), public branch looking for feedback)
- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), public branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), public branch looking for feedback)
- Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
- Add an automation and testing system, both to test the library and end-user apps. - Add an automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435))
- Make Columns better. (they are currently pretty terrible!) - Make Columns better. (they are currently pretty terrible!)
- Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. - Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware.
@ -291,30 +294,39 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
Support dear imgui Support dear imgui
------------------ ------------------
**How can I help?**
- You may participate in the Discourse and GitHub [issues trackers](https://github.com/ocornut/imgui/issues).
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the Wiki for some more ideas.
- Convince your company to financially support this project.
**How can I help financing further development of Dear ImGui?** **How can I help financing further development of Dear ImGui?**
Your contributions are keeping the library alive. If you are an individual using dear imgui, please consider donating to enable me to spend more time improving the library. Your contributions are keeping this project alive. The library is free as in freedom, but continued maintenance and development are a full-time endeavor. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. Thank you!
Monthly donations via Patreon: Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) <br>&nbsp;[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)
One-off donations via PayPal: Individuals/hobbyists: support continued maintenance and development via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) <br>&nbsp;&nbsp;[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui) and by private sponsors. Businesses: support continued maintenance and development via support contracts or sponsoring a few weeks/months of development:
If your company uses dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development. I can also invoice for private support, custom development etc. contact me for details: omarcornut at gmail). Thanks! <br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Ongoing dear imgui development is financially supported by users and private sponsors (past and present):
**Platinum-chocolate sponsors** **Platinum-chocolate sponsors**
- Blizzard Entertainment. - **Blizzard Entertainment**.
**Double-chocolate sponsors** **Double-chocolate sponsors**
- Media Molecule, Mobigame, Insomniac Games, Aras Pranckevičius, Lizardcube, Greggman, DotEmu, Nadeo, Supercell, Runner. - Media Molecule, Mobigame, Insomniac Games, Aras Pranckevičius, Lizardcube, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss.
**Salty caramel supporters** **Salty caramel supporters**
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts. - Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc.
**Caramel supporters** **Caramel supporters**
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Astrofra, Jonas Lehmann, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa. - Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Astrofra, Jonas Lehmann, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos.
And all other supporters; THANK YOU! And all other supporters; THANK YOU!
(Please contact me if you would like to be added or removed from this list) (Please contact me if you would like to be added or removed from this list)

102
imgui.cpp
View File

@ -2658,7 +2658,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None; window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
ImGuiTestEngineHook_ItemAdd(id, bb); ImGuiTestEngineHook_ItemAdd(bb, id);
#endif #endif
// Clipping test // Clipping test
@ -3433,7 +3433,7 @@ void ImGui::NewFrame()
// No window should be open at the beginning of the frame. // No window should be open at the beginning of the frame.
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
g.CurrentWindowStack.resize(0); g.CurrentWindowStack.resize(0);
g.CurrentPopupStack.resize(0); g.BeginPopupStack.resize(0);
ClosePopupsOverWindow(g.NavWindow); ClosePopupsOverWindow(g.NavWindow);
// Create implicit/fallback window - which we will only render it if the user has added something to it. // Create implicit/fallback window - which we will only render it if the user has added something to it.
@ -3520,7 +3520,7 @@ void ImGui::Shutdown(ImGuiContext* context)
g.StyleModifiers.clear(); g.StyleModifiers.clear();
g.FontStack.clear(); g.FontStack.clear();
g.OpenPopupStack.clear(); g.OpenPopupStack.clear();
g.CurrentPopupStack.clear(); g.BeginPopupStack.clear();
g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL; g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL;
for (int i = 0; i < g.Viewports.Size; i++) for (int i = 0; i < g.Viewports.Size; i++)
IM_DELETE(g.Viewports[i]); IM_DELETE(g.Viewports[i]);
@ -4149,8 +4149,8 @@ ImVec2 ImGui::GetMousePos()
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.CurrentPopupStack.Size > 0) if (g.BeginPopupStack.Size > 0)
return g.OpenPopupStack[g.CurrentPopupStack.Size-1].OpenMousePos; return g.OpenPopupStack[g.BeginPopupStack.Size-1].OpenMousePos;
return g.IO.MousePos; return g.IO.MousePos;
} }
@ -4423,7 +4423,7 @@ static void CheckStacksSize(ImGuiWindow* window, bool write)
short* p_backup = &window->DC.StackSizesBackup[0]; short* p_backup = &window->DC.StackSizesBackup[0];
{ int current = window->IDStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop() { int current = window->IDStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop()
{ int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup() { int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup()
{ int current = g.CurrentPopupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup() { int current = g.BeginPopupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup()
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
{ int current = g.ColorModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor() { int current = g.ColorModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor()
{ int current = g.StyleModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar() { int current = g.StyleModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar()
@ -4852,7 +4852,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0); const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0);
if (flags & ImGuiWindowFlags_Popup) if (flags & ImGuiWindowFlags_Popup)
{ {
ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
window_just_activated_by_user |= (window != popup_ref.Window); window_just_activated_by_user |= (window != popup_ref.Window);
} }
@ -4886,9 +4886,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
CheckStacksSize(window, true); CheckStacksSize(window, true);
if (flags & ImGuiWindowFlags_Popup) if (flags & ImGuiWindowFlags_Popup)
{ {
ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
popup_ref.Window = window; popup_ref.Window = window;
g.CurrentPopupStack.push_back(popup_ref); g.BeginPopupStack.push_back(popup_ref);
window->PopupId = popup_ref.PopupId; window->PopupId = popup_ref.PopupId;
} }
@ -5076,7 +5076,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{ {
window->AutoPosLastDirection = ImGuiDir_None; window->AutoPosLastDirection = ImGuiDir_None;
if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
window->Pos = g.CurrentPopupStack.back().OpenPopupPos; window->Pos = g.BeginPopupStack.back().OpenPopupPos;
} }
// Position child window // Position child window
@ -5553,7 +5553,7 @@ void ImGui::End()
// Pop from window stack // Pop from window stack
g.CurrentWindowStack.pop_back(); g.CurrentWindowStack.pop_back();
if (window->Flags & ImGuiWindowFlags_Popup) if (window->Flags & ImGuiWindowFlags_Popup)
g.CurrentPopupStack.pop_back(); g.BeginPopupStack.pop_back();
CheckStacksSize(window, false); CheckStacksSize(window, false);
SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
if (g.CurrentWindow) if (g.CurrentWindow)
@ -6781,13 +6781,13 @@ void ImGui::SetTooltip(const char* fmt, ...)
bool ImGui::IsPopupOpen(ImGuiID id) bool ImGui::IsPopupOpen(ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id; return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
} }
bool ImGui::IsPopupOpen(const char* str_id) bool ImGui::IsPopupOpen(const char* str_id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id); return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
} }
ImGuiWindow* ImGui::GetFrontMostPopupModal() ImGuiWindow* ImGui::GetFrontMostPopupModal()
@ -6814,7 +6814,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = g.CurrentWindow; ImGuiWindow* parent_window = g.CurrentWindow;
int current_stack_size = g.CurrentPopupStack.Size; int current_stack_size = g.BeginPopupStack.Size;
ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
popup_ref.PopupId = id; popup_ref.PopupId = id;
popup_ref.Window = NULL; popup_ref.Window = NULL;
@ -6873,12 +6873,13 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window)
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
// Don't close our own child popup windows. // Don't close our own child popup windows.
int n = 0; int popup_count_to_keep = 0;
if (ref_window) if (ref_window)
{ {
for (; n < g.OpenPopupStack.Size; n++) // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
{ {
ImGuiPopupRef& popup = g.OpenPopupStack[n]; ImGuiPopupRef& popup = g.OpenPopupStack[popup_count_to_keep];
if (!popup.Window) if (!popup.Window)
continue; continue;
IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
@ -6886,47 +6887,60 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window)
continue; continue;
// Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow) // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow)
bool has_focus = false; bool popup_or_descendent_has_focus = false;
for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) for (int m = popup_count_to_keep; m < g.OpenPopupStack.Size && !popup_or_descendent_has_focus; m++)
has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow); if (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow)
if (!has_focus) popup_or_descendent_has_focus = true;
if (!popup_or_descendent_has_focus)
break; break;
} }
} }
if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
ClosePopupToLevel(n); {
//IMGUI_DEBUG_LOG("ClosePopupsOverWindow(%s) -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
ClosePopupToLevel(popup_count_to_keep, false);
}
} }
void ImGui::ClosePopupToLevel(int remaining) void ImGui::ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
{ {
IM_ASSERT(remaining >= 0); IM_ASSERT(remaining >= 0);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow; ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow;
g.OpenPopupStack.resize(remaining);
// FIXME: This code is faulty and we may want to eventually to replace or remove the 'apply_focus_to_window_under=true' path completely.
// Instead of using g.OpenPopupStack[remaining-1].Window etc. we should find the highest root window that is behind the popups we are closing.
// The current code will set focus to the parent of the popup window which is incorrect.
// It rarely manifested until now because UpdateMouseMovingWindow() would call FocusWindow() again on the clicked window,
// leading to a chain of focusing A (clicked window) then B (parent window of the popup) then A again.
// However if the clicked window has the _NoMove flag set we would be left with B focused.
// For now, we have disabled this path when called from ClosePopupsOverWindow() because the users of ClosePopupsOverWindow() don't need to alter focus anyway,
// but we should inspect and fix this properly.
if (apply_focus_to_window_under)
{
if (g.NavLayer == 0) if (g.NavLayer == 0)
focus_window = NavRestoreLastChildNavWindow(focus_window); focus_window = NavRestoreLastChildNavWindow(focus_window);
FocusWindow(focus_window); FocusWindow(focus_window);
focus_window->DC.NavHideHighlightOneFrame = true; }
g.OpenPopupStack.resize(remaining);
}
void ImGui::ClosePopup(ImGuiID id)
{
if (!IsPopupOpen(id))
return;
ImGuiContext& g = *GImGui;
ClosePopupToLevel(g.OpenPopupStack.Size - 1);
} }
// Close the popup we have begin-ed into. // Close the popup we have begin-ed into.
void ImGui::CloseCurrentPopup() void ImGui::CloseCurrentPopup()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
int popup_idx = g.CurrentPopupStack.Size - 1; int popup_idx = g.BeginPopupStack.Size - 1;
if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
return; return;
while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu))
popup_idx--; popup_idx--;
ClosePopupToLevel(popup_idx); ClosePopupToLevel(popup_idx, true);
// A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
// To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
// Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
if (ImGuiWindow* window = g.NavWindow)
window->DC.NavHideHighlightOneFrame = true;
} }
bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
@ -6940,7 +6954,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
char name[20]; char name[20];
if (extra_flags & ImGuiWindowFlags_ChildMenu) if (extra_flags & ImGuiWindowFlags_ChildMenu)
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
else else
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
@ -6954,7 +6968,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
{ {
g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
return false; return false;
@ -6963,6 +6977,8 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags); return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags);
} }
// If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
// Note that popup visibility status is owned by imgui (and manipulated with e.g. OpenPopup) so the actual value of *p_open is meaningless here.
bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -6985,7 +7001,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
{ {
EndPopup(); EndPopup();
if (is_open) if (is_open)
ClosePopup(id); ClosePopupToLevel(g.BeginPopupStack.Size, true);
return false; return false;
} }
return is_open; return is_open;
@ -6995,7 +7011,7 @@ void ImGui::EndPopup()
{ {
ImGuiContext& g = *GImGui; (void)g; ImGuiContext& g = *GImGui; (void)g;
IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
IM_ASSERT(g.CurrentPopupStack.Size > 0); IM_ASSERT(g.BeginPopupStack.Size > 0);
// Make all menus and popups wrap around for now, may need to expose that policy. // Make all menus and popups wrap around for now, may need to expose that policy.
NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY); NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY);
@ -7590,7 +7606,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{ {
// We need to take account of the possibility that mouse may become invalid. // We need to take account of the possibility that mouse may become invalid.
// Popups/Tooltip always set ViewportAllowPlatformMonitorExtend so GetWindowAllowedExtentRect() will return full monitor bounds. // Popups/Tooltip always set ViewportAllowPlatformMonitorExtend so GetWindowAllowedExtentRect() will return full monitor bounds.
ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.CurrentPopupStack.back().OpenMousePos; ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.BeginPopupStack.back().OpenMousePos;
bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow); bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow);
bool mouse_valid = IsMousePosValid(&mouse_ref); bool mouse_valid = IsMousePosValid(&mouse_ref);
if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid)) if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid))
@ -8403,7 +8419,7 @@ static void ImGui::NavUpdate()
{ {
// Close open popup/menu // Close open popup/menu
if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
ClosePopupToLevel(g.OpenPopupStack.Size - 1); ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
} }
else if (g.NavLayer != 0) else if (g.NavLayer != 0)
{ {

18
imgui.h
View File

@ -233,7 +233,8 @@ namespace ImGui
// which clicking will set the boolean to false when clicked. // which clicking will set the boolean to false when clicked.
// - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting
// anything to the window. Always call a matching End() for each Begin() call, regardless of its return value! // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value!
// [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function returned true.] // [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc.
// where the EndXXX call should only be called if the corresponding BeginXXX function returned true.]
// - Note that the bottom of window stack always contains a window called "Debug". // - Note that the bottom of window stack always contains a window called "Debug".
IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
IMGUI_API void End(); IMGUI_API void End();
@ -521,7 +522,14 @@ namespace ImGui
IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip().
IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Popups // Popups, Modals
// The properties of popups windows are:
// - They block normal mouse hovering detection outside them. (*)
// - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
// - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
// User can manipulate the visibility state by calling OpenPopup().
// (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
// Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true! IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true!
IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
@ -530,11 +538,11 @@ namespace ImGui
IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside) IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside)
IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened. IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened.
IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open at the current begin-ed level of the popup stack.
IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup.
// Columns // Columns
// You can also use SameLine(pos_x) for simplified columns. The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) // You can also use SameLine(pos_x) to mimic simplified columns. The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!)
IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true);
IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished
IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API int GetColumnIndex(); // get current column index
@ -553,7 +561,7 @@ namespace ImGui
IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
// Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging. // Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging.
IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty (stdout)
IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file
IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard
IMGUI_API void LogFinish(); // stop logging (close file, etc.) IMGUI_API void LogFinish(); // stop logging (close file, etc.)

View File

@ -1992,12 +1992,13 @@ static void ShowDemoWindowPopups()
if (!ImGui::CollapsingHeader("Popups & Modal windows")) if (!ImGui::CollapsingHeader("Popups & Modal windows"))
return; return;
// Popups are windows with a few special properties: // The properties of popups windows are:
// - They block normal mouse hovering detection outside them. (*) // - They block normal mouse hovering detection outside them. (*)
// - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
// - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls. // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
// User can manipulate the visibility state by calling OpenPopup().
// (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup. // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
// Those three properties are intimately connected. The library needs to hold their visibility state because it can close popups at any time. // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
// Typical use for regular windows: // Typical use for regular windows:
// bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End(); // bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
@ -2126,6 +2127,7 @@ static void ShowDemoWindowPopups()
if (ImGui::Button("Delete..")) if (ImGui::Button("Delete.."))
ImGui::OpenPopup("Delete?"); ImGui::OpenPopup("Delete?");
if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{ {
ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
@ -2158,7 +2160,11 @@ static void ShowDemoWindowPopups()
if (ImGui::Button("Add another modal..")) if (ImGui::Button("Add another modal.."))
ImGui::OpenPopup("Stacked 2"); ImGui::OpenPopup("Stacked 2");
if (ImGui::BeginPopupModal("Stacked 2"))
// Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which will close the popup.
// Note that the visibility state of popups is owned by imgui, so the input value of the bool actually doesn't matter here.
bool dummy_open = true;
if (ImGui::BeginPopupModal("Stacked 2", &dummy_open))
{ {
ImGui::Text("Hello from Stacked The Second!"); ImGui::Text("Hello from Stacked The Second!");
if (ImGui::Button("Close")) if (ImGui::Button("Close"))

View File

@ -801,7 +801,7 @@ struct ImGuiContext
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent) ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupRef> CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector<ImGuiPopupRef> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions
ImGuiCond NextTreeNodeOpenCond; ImGuiCond NextTreeNodeOpenCond;
@ -1369,10 +1369,9 @@ namespace ImGui
// Popups, Modals, Tooltips // Popups, Modals, Tooltips
IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void OpenPopupEx(ImGuiID id);
IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API void ClosePopupToLevel(int remaining, bool apply_focus_to_window_under);
IMGUI_API void ClosePopupToLevel(int remaining);
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window);
IMGUI_API bool IsPopupOpen(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id within current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack!
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true);
IMGUI_API ImGuiWindow* GetFrontMostPopupModal(); IMGUI_API ImGuiWindow* GetFrontMostPopupModal();
@ -1499,7 +1498,7 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned ch
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
extern void ImGuiTestEngineHook_PreNewFrame(); extern void ImGuiTestEngineHook_PreNewFrame();
extern void ImGuiTestEngineHook_PostNewFrame(); extern void ImGuiTestEngineHook_PostNewFrame();
extern void ImGuiTestEngineHook_ItemAdd(ImGuiID id, const ImRect& bb); extern void ImGuiTestEngineHook_ItemAdd(const ImRect& bb, ImGuiID id);
extern void ImGuiTestEngineHook_ItemInfo(ImGuiID id, const char* label, int flags); extern void ImGuiTestEngineHook_ItemInfo(ImGuiID id, const char* label, int flags);
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) ImGuiTestEngineHook_ItemInfo(_ID, _LABEL, _FLAGS) // Register status flags #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) ImGuiTestEngineHook_ItemInfo(_ID, _LABEL, _FLAGS) // Register status flags
#else #else

View File

@ -396,6 +396,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window)
g.HoveredWindow = window; g.HoveredWindow = window;
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (window->DC.LastItemId != id)
ImGuiTestEngineHook_ItemAdd(bb, id);
#endif
bool pressed = false; bool pressed = false;
bool hovered = ItemHoverable(bb, id); bool hovered = ItemHoverable(bb, id);
@ -1332,7 +1337,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
} }
char name[16]; char name[16];
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
// Peak into expected window size so we can position it // Peak into expected window size so we can position it
if (ImGuiWindow* popup_window = FindWindowByName(name)) if (ImGuiWindow* popup_window = FindWindowByName(name))
@ -5563,7 +5568,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
bool pressed; bool pressed;
bool menu_is_open = IsPopupOpen(id); bool menu_is_open = IsPopupOpen(id);
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].OpenParentId == window->IDStack.back()); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
ImGuiWindow* backed_nav_window = g.NavWindow; ImGuiWindow* backed_nav_window = g.NavWindow;
if (menuset_is_open) if (menuset_is_open)
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
@ -5604,9 +5609,9 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
{ {
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
bool moving_within_opened_triangle = false; bool moving_within_opened_triangle = false;
if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar)) if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar))
{ {
if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) if (ImGuiWindow* next_window = g.OpenPopupStack[g.BeginPopupStack.Size].Window)
{ {
ImRect next_window_rect = next_window->Rect(); ImRect next_window_rect = next_window->Rect();
ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
@ -5657,11 +5662,11 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
want_close = true; want_close = true;
if (want_close && IsPopupOpen(id)) if (want_close && IsPopupOpen(id))
ClosePopupToLevel(g.CurrentPopupStack.Size); ClosePopupToLevel(g.BeginPopupStack.Size, true);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{ {
// Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
OpenPopup(label); OpenPopup(label);
@ -5687,14 +5692,14 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
void ImGui::EndMenu() void ImGui::EndMenu()
{ {
// Nav: When a left move request _within our child menu_ failed, close the menu. // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
// A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs. // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
// However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction. // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
{ {
ClosePopupToLevel(g.OpenPopupStack.Size - 1); ClosePopupToLevel(g.BeginPopupStack.Size, true);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }