diff --git a/3rdparty/dear-imgui/imgui.cpp b/3rdparty/dear-imgui/imgui.cpp index 7973498ab..1e019b62c 100644 --- a/3rdparty/dear-imgui/imgui.cpp +++ b/3rdparty/dear-imgui/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.61 +// dear imgui, v1.62 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. @@ -2254,7 +2254,7 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items) // For example, this ensure that items in one column are not reached when moving vertically from items in another column. - NavClampRectToVisibleAreaForMoveDir(g.NavMoveDir, cand, window->ClipRect); + NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); // Compute distance between boxes // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. @@ -3008,39 +3008,35 @@ static void ImGui::NavUpdateWindowing() } // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. -static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel) +static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) { // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1, 1), window->InnerMainRect.Max - window->Pos + ImVec2(1, 1)); - //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (window_rect_rel.Contains(item_rect_rel)) + ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1)); + //g.OverlayDrawList.AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect.Contains(item_rect)) return; ImGuiContext& g = *GImGui; - if (window->ScrollbarX && item_rect_rel.Min.x < window_rect_rel.Min.x) + if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) { - window->ScrollTarget.x = item_rect_rel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; window->ScrollTargetCenterRatio.x = 0.0f; } - else if (window->ScrollbarX && item_rect_rel.Max.x >= window_rect_rel.Max.x) + else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) { - window->ScrollTarget.x = item_rect_rel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; window->ScrollTargetCenterRatio.x = 1.0f; } - if (item_rect_rel.Min.y < window_rect_rel.Min.y) + if (item_rect.Min.y < window_rect.Min.y) { - window->ScrollTarget.y = item_rect_rel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; window->ScrollTargetCenterRatio.y = 0.0f; } - else if (item_rect_rel.Max.y >= window_rect_rel.Max.y) + else if (item_rect.Max.y >= window_rect.Max.y) { - window->ScrollTarget.y = item_rect_rel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; window->ScrollTargetCenterRatio.y = 1.0f; } - - // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately after in NavUpdate() - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window, false); - item_rect_rel.Translate(window->Scroll - next_scroll); } static void ImGui::NavUpdate() @@ -3104,9 +3100,18 @@ static void ImGui::NavUpdate() IM_ASSERT(g.NavWindow && result->Window); - // Scroll to keep newly navigated item fully into view + // Scroll to keep newly navigated item fully into view. Also scroll parent window if necessary. if (g.NavLayer == 0) - NavScrollToBringItemIntoView(result->Window, result->RectRel); + { + ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); + NavScrollToBringItemIntoView(result->Window, rect_abs); + if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) + NavScrollToBringItemIntoView(result->Window->ParentWindow, rect_abs); + + // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate() + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false); + result->RectRel.Translate(result->Window->Scroll - next_scroll); + } // Apply result from previous frame navigation directional move request ClearActiveID(); @@ -3225,6 +3230,7 @@ static void ImGui::NavUpdate() if (g.NavMoveRequestForward == ImGuiNavForward_None) { g.NavMoveDir = ImGuiDir_None; + g.NavMoveRequestFlags = 0; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { if ((allowed_dir_flags & (1<DC.CursorPos; int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); - if (g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Up) // When performing a navigation request, ensure we have one item extra in the direction we are moving to + + // When performing a navigation request, ensure we have one item extra in the direction we are moving to + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) start--; - if (g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) + if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) end++; start = ImClamp(start, 0, items_count); @@ -5099,16 +5109,51 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla return is_open; } -static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) +void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags) { ImGuiContext& g = *GImGui; - if (g.NavWindow == window && NavMoveRequestButNoResultYet()) - if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) - { - g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; - ImGui::NavMoveRequestCancel(); - g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y; - } + IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); + ImGui::NavMoveRequestCancel(); + g.NavMoveDir = move_dir; + g.NavMoveClipDir = clip_dir; + g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; + g.NavMoveRequestFlags = move_flags; + g.NavWindow->NavRectRel[g.NavLayer] = bb_rel; +} + +void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags) +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0) + return; + IM_ASSERT(move_flags != 0); // No points calling this with no wrapping + ImRect bb_rel = window->NavRectRel[0]; + + ImGuiDir clip_dir = g.NavMoveDir; + if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) + { + bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x; + if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) + { + bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x; + if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) + { + bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y; + if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } + if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) + { + bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y; + if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; } + NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); + } } void ImGui::EndPopup() @@ -5118,7 +5163,7 @@ void ImGui::EndPopup() IM_ASSERT(g.CurrentPopupStack.Size > 0); // Make all menus and popups wrap around for now, may need to expose that policy. - NavProcessMoveRequestWrapAround(g.CurrentWindow); + NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY); End(); } @@ -6156,7 +6201,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->SizeFullAtLastBegin = window->SizeFull; // Update various regions. Variables they depends on are set above in this function. - // FIXME: window->ContentsRegion.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. + // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); @@ -8067,7 +8112,7 @@ void ImGui::LogButtons() bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_Leaf) - return true; + return false; // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions) ImGuiContext& g = *GImGui; diff --git a/3rdparty/dear-imgui/imgui.h b/3rdparty/dear-imgui/imgui.h index bf2736d6a..eac6df37f 100644 --- a/3rdparty/dear-imgui/imgui.h +++ b/3rdparty/dear-imgui/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.61 +// dear imgui, v1.62 WIP // (headers) // See imgui.cpp file for documentation. @@ -22,7 +22,7 @@ #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp // Version -#define IMGUI_VERSION "1.61" +#define IMGUI_VERSION "1.62 WIP" #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) @@ -1236,8 +1236,10 @@ public: return; value_type* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); if (Data) + { memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); - ImGui::MemFree(Data); + ImGui::MemFree(Data); + } Data = new_data; Capacity = new_capacity; } diff --git a/3rdparty/dear-imgui/imgui_demo.cpp b/3rdparty/dear-imgui/imgui_demo.cpp index fcff50657..2f458f7ca 100644 --- a/3rdparty/dear-imgui/imgui_demo.cpp +++ b/3rdparty/dear-imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.61 +// dear imgui, v1.62 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: @@ -457,9 +457,9 @@ void ImGui::ShowDemoWindow(bool* p_open) else { // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). - node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet + node_flags |= ImGuiTreeNodeFlags_Leaf; // | ImGuiTreeNodeFlags_Bullet; ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); - if (ImGui::IsItemClicked()) + if (ImGui::IsItemClicked()) node_clicked = i; } } @@ -3188,13 +3188,9 @@ static void ShowExampleAppPropertyEditor(bool* p_open) } else { + // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) ImGui::AlignTextToFramePadding(); - // Here we use a Selectable (instead of Text) to highlight on hover - //ImGui::Text("Field_%d", i); - char label[32]; - sprintf(label, "Field_%d", i); - ImGui::Bullet(); - ImGui::Selectable(label); + ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet, "Field_%d", i); ImGui::NextColumn(); ImGui::PushItemWidth(-1); if (i >= 5) diff --git a/3rdparty/dear-imgui/imgui_draw.cpp b/3rdparty/dear-imgui/imgui_draw.cpp index 8ba9f098d..59995c97f 100644 --- a/3rdparty/dear-imgui/imgui_draw.cpp +++ b/3rdparty/dear-imgui/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.61 +// dear imgui, v1.62 WIP // (drawing and font code) // Contains implementation for diff --git a/3rdparty/dear-imgui/imgui_internal.h b/3rdparty/dear-imgui/imgui_internal.h index 7ec9aa9ac..4bacdd89d 100644 --- a/3rdparty/dear-imgui/imgui_internal.h +++ b/3rdparty/dear-imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.61 +// dear imgui, v1.62 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -50,6 +50,7 @@ typedef int ImGuiItemFlags; // flags: for PushItemFlag() typedef int ImGuiItemStatusFlags; // flags: storage for DC.LastItemXXX // enum ImGuiItemStatusFlags_ typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_ typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_ +typedef int ImGuiNavMoveFlags; // flags: for navigation requests // enum ImGuiNavMoveFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ @@ -302,6 +303,14 @@ enum ImGuiNavDirSourceFlags_ ImGuiNavDirSourceFlags_PadLStick = 1 << 2 }; +enum ImGuiNavMoveFlags_ +{ + ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side + ImGuiNavMoveFlags_LoopY = 1 << 1, + ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) + ImGuiNavMoveFlags_WrapY = 1 << 3 // This is not super useful for provided for completeness +}; + enum ImGuiNavForward { ImGuiNavForward_None, @@ -337,6 +346,8 @@ struct IMGUI_API ImRect void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; } + void TranslateX(float dx) { Min.x += dx; Max.x += dx; } + void TranslateY(float dy) { Min.y += dy; Max.y += dy; } void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } @@ -645,8 +656,10 @@ struct ImGuiContext ImRect NavInitResultRectRel; bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame + ImGuiNavMoveFlags NavMoveRequestFlags; ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request + ImGuiDir NavMoveClipDir; ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using the NavFlattened flag) @@ -762,8 +775,9 @@ struct ImGuiContext NavInitResultId = 0; NavMoveFromClampedRefRect = false; NavMoveRequest = false; + NavMoveRequestFlags = 0; NavMoveRequestForward = ImGuiNavForward_None; - NavMoveDir = NavMoveDirLast = ImGuiDir_None; + NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; ModalWindowDarkeningRatio = 0.0f; OverlayDrawList._Data = &DrawListSharedData; @@ -1069,6 +1083,8 @@ namespace ImGui IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API void NavMoveRequestCancel(); + IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags); + IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);