diff --git a/backends/imgui_impl_metal.h b/backends/imgui_impl_metal.h index 8407290f..4f7c7f8f 100644 --- a/backends/imgui_impl_metal.h +++ b/backends/imgui_impl_metal.h @@ -45,9 +45,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects(); // More info about using Metal from C++: https://developer.apple.com/metal/cpp/ #ifdef IMGUI_IMPL_METAL_CPP - #include - #ifndef __OBJC__ IMGUI_IMPL_API bool ImGui_ImplMetal_Init(MTL::Device* device); @@ -64,5 +62,4 @@ IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device); IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects(); #endif - #endif diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index dfadfba8..dd14b501 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -92,12 +92,12 @@ static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CF bool ImGui_ImplMetal_Init(MTL::Device* device) { - return ImGui_ImplMetal_Init((id)(device)); + return ImGui_ImplMetal_Init((__bridge id)(device)); } void ImGui_ImplMetal_NewFrame(MTL::RenderPassDescriptor* renderPassDescriptor) { - ImGui_ImplMetal_NewFrame((MTLRenderPassDescriptor*)(renderPassDescriptor)); + ImGui_ImplMetal_NewFrame((__bridge MTLRenderPassDescriptor*)(renderPassDescriptor)); } void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, @@ -105,19 +105,19 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, MTL::RenderCommandEncoder* commandEncoder) { ImGui_ImplMetal_RenderDrawData(draw_data, - (id)(commandBuffer), - (id)(commandEncoder)); + (__bridge id)(commandBuffer), + (__bridge id)(commandEncoder)); } bool ImGui_ImplMetal_CreateFontsTexture(MTL::Device* device) { - return ImGui_ImplMetal_CreateFontsTexture((id)(device)); + return ImGui_ImplMetal_CreateFontsTexture((__bridge id)(device)); } bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device) { - return ImGui_ImplMetal_CreateDeviceObjects((id)(device)); + return ImGui_ImplMetal_CreateDeviceObjects((__bridge id)(device)); } #endif // #ifdef IMGUI_IMPL_METAL_CPP @@ -589,8 +589,8 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows() { if ((self = [super init])) { - _renderPipelineStateCache = [NSMutableDictionary dictionary]; - _bufferCache = [NSMutableArray array]; + self.renderPipelineStateCache = [NSMutableDictionary dictionary]; + self.bufferCache = [NSMutableArray array]; _lastBufferCachePurge = GetMachAbsoluteTimeInSeconds(); } return self; diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 18a7554f..99388a1b 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -17,9 +17,28 @@ #include "imgui.h" // IMGUI_IMPL_API +#ifdef __OBJC__ + @class NSEvent; @class NSView; IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view); IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view); + +#endif + +//----------------------------------------------------------------------------- +// C++ API +//----------------------------------------------------------------------------- + +#ifdef IMGUI_IMPL_METAL_CPP_EXTENSIONS +// #include +#ifndef __OBJC__ + +IMGUI_IMPL_API bool ImGui_ImplOSX_Init(void* _Nonnull view); +IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view); + +#endif +#endif diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index c95cf91c..1da47542 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -376,6 +376,18 @@ static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code) } } +#ifdef IMGUI_IMPL_METAL_CPP_EXTENSIONS + +IMGUI_IMPL_API bool ImGui_ImplOSX_Init(void* _Nonnull view) { + return ImGui_ImplOSX_Init((__bridge NSView*)(view)); +} + +IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) { + return ImGui_ImplOSX_NewFrame((__bridge NSView*)(view)); +} + +#endif + bool ImGui_ImplOSX_Init(NSView* view) { diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index caaf6315..4204485b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -106,6 +106,11 @@ Breaking changes: Other Changes: +- InputText: added experimental io.ConfigInputTextEnterKeepActive feature to make pressing + Enter keep the input active and select all text. +- Backends: Metal: Use __bridge for ARC based systems. (#5403) [@stack] +- Backends: OSX: Fixes to support full app creation in C++. (#5403) [@stack] + Docking+Viewports Branch: - Backends: GLFW: Fixed leftover static variable preventing from changing or diff --git a/imgui.cpp b/imgui.cpp index 9f33cb17..a67501c8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index a8a2f73a..b002d2e8 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (headers) // Help: @@ -64,8 +64,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.88" -#define IMGUI_VERSION_NUM 18800 +#define IMGUI_VERSION "1.89 WIP" +#define IMGUI_VERSION_NUM 18802 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE #define IMGUI_HAS_VIEWPORT // Viewport WIP branch @@ -2023,6 +2023,7 @@ struct ImGuiIO bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). + bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index da687a55..911d5f73 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (demo code) // Help: @@ -527,6 +527,8 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates."); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)."); + ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive); + ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only)."); ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText); ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving)."); ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 830ae3f0..82e1925a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 145236d3..23f5b944 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -767,6 +767,7 @@ struct ImDrawDataBuilder // This is going to be exposed in imgui.h when stabilized enough. enum ImGuiItemFlags_ { + // Controlled by user ImGuiItemFlags_None = 0, ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav) ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. @@ -776,6 +777,8 @@ enum ImGuiItemFlags_ ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. + + // Controlled by widget code ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. }; @@ -2861,17 +2864,6 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - // Currently refactoring focus/nav/tabbing system - // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): - // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' - // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' - // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP) - // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() - inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() - inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem -#endif - // Logging/Capture IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer @@ -3039,6 +3031,7 @@ namespace ImGui IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table); IMGUI_API void TableDrawBorders(ImGuiTable* table); IMGUI_API void TableDrawContextMenu(ImGuiTable* table); + IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table); IMGUI_API void TableMergeDrawChannels(ImGuiTable* table); inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; } IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table); @@ -3133,8 +3126,9 @@ namespace ImGui IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); - IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging IMGUI_API void TreePushOverrideID(ImGuiID id); + IMGUI_API void TreeNodeSetOpen(ImGuiID id, bool open); + IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging. // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). @@ -3207,6 +3201,19 @@ namespace ImGui IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport); IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb); + // Obsolete functions +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89 + + // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): + // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' + // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' + // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP) + // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() + inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() + inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem +#endif + } // namespace ImGui diff --git a/imgui_tables.cpp b/imgui_tables.cpp index c3e24af3..9b18f41d 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (tables and columns code) /* @@ -1105,18 +1105,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->IsUsingHeaders = false; // [Part 11] Context menu - if (table->IsContextPopupOpen && table->InstanceCurrent == table->InstanceInteracted) + if (TableBeginContextMenuPopup(table)) { - const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); - if (BeginPopupEx(context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) - { - TableDrawContextMenu(table); - EndPopup(); - } - else - { - table->IsContextPopupOpen = false; - } + TableDrawContextMenu(table); + EndPopup(); } // [Part 13] Sanitize and build sort specs before we have a change to use them for display. @@ -3035,6 +3027,17 @@ void ImGui::TableOpenContextMenu(int column_n) } } +bool ImGui::TableBeginContextMenuPopup(ImGuiTable* table) +{ + if (!table->IsContextPopupOpen || table->InstanceCurrent != table->InstanceInteracted) + return false; + const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); + if (BeginPopupEx(context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) + return true; + table->IsContextPopupOpen = false; + return false; +} + // Output context menu into current window (generally a popup) // FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data? void ImGui::TableDrawContextMenu(ImGuiTable* table) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7cb93667..b57639f3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.88 +// dear imgui, v1.89 WIP // (widgets code) /* @@ -3603,7 +3603,7 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { - IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() + IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() or InputTextEx() manually if you need multi-line + hint. return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } @@ -4179,7 +4179,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active); bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); bool value_changed = false; - bool enter_pressed = false; + bool validated = false; // When read-only we always use the live data passed to the function // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :( @@ -4346,9 +4346,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_redo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressed(ImGuiKey_Z))) && !is_readonly && is_undoable; // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. - const bool is_validate_enter = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter); + const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter); const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiNavReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiNavReadMode_Pressed); - const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed); + const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed); if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } @@ -4370,12 +4370,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } - else if (is_validate_enter) + else if (is_enter_pressed) { + // Determine if we turn Enter into a \n character bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) { - enter_pressed = clear_active_id = true; + validated = true; + if (io.ConfigInputTextEnterKeepActive && !is_multiline) + state->SelectAll(); // No need to scroll + else + clear_active_id = true; } else if (!is_readonly) { @@ -4386,8 +4391,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } else if (is_validate_nav) { - IM_ASSERT(!is_validate_enter); - enter_pressed = clear_active_id = true; + IM_ASSERT(!is_enter_pressed); + validated = clear_active_id = true; } else if (is_cancel) { @@ -4491,7 +4496,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). - const bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + const bool apply_edit_back_to_user_buffer = !cancel_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); if (apply_edit_back_to_user_buffer) { // Apply new value immediately - copy modified buffer back @@ -4868,7 +4873,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) - return enter_pressed; + return validated; else return value_changed; } @@ -5904,7 +5909,14 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char return TreeNodeBehavior(window->GetID(ptr_id), flags, label, label_end); } -bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) +void ImGui::TreeNodeSetOpen(ImGuiID id, bool open) +{ + ImGuiContext& g = *GImGui; + ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage; + storage->SetInt(id, open ? 1 : 0); +} + +bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_Leaf) return true; @@ -5920,7 +5932,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) if (g.NextItemData.OpenCond & ImGuiCond_Always) { is_open = g.NextItemData.OpenVal; - storage->SetInt(id, is_open); + TreeNodeSetOpen(id, is_open); } else { @@ -5929,7 +5941,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) if (stored_value == -1) { is_open = g.NextItemData.OpenVal; - storage->SetInt(id, is_open); + TreeNodeSetOpen(id, is_open); } else { @@ -5995,7 +6007,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; - bool is_open = TreeNodeBehaviorIsOpen(id, flags); + bool is_open = TreeNodeUpdateNextOpen(id, flags); if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);