WIP Menus: Implement amazon's dropdown-like triangle test for navigating sub-menus (#126)
This commit is contained in:
parent
63a39dd08e
commit
d009a85de4
31
imgui.cpp
31
imgui.cpp
@ -729,6 +729,14 @@ static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t)
|
||||
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
||||
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
|
||||
|
||||
static bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c)
|
||||
{
|
||||
bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
|
||||
bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
|
||||
bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
|
||||
return ((b1 == b2) && (b2 == b3));
|
||||
}
|
||||
|
||||
static int ImStricmp(const char* str1, const char* str2)
|
||||
{
|
||||
int d;
|
||||
@ -7613,9 +7621,28 @@ bool ImGui::BeginMenu(const char* label)
|
||||
bool want_open = false;
|
||||
if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
|
||||
{
|
||||
if (opened && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id)
|
||||
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive.
|
||||
bool moving_within_opened_triangle = false;
|
||||
if (g.HoveredWindow == window && g.OpenedPopupStack.size() > g.CurrentPopupStack.size() && g.OpenedPopupStack[g.CurrentPopupStack.size()].ParentWindow == window)
|
||||
{
|
||||
if (ImGuiWindow* next_window = g.OpenedPopupStack[g.CurrentPopupStack.size()].Window)
|
||||
{
|
||||
ImRect next_window_rect = next_window->Rect();
|
||||
ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
|
||||
ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
|
||||
ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
|
||||
float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. all sizes are hard-coded in pixels, need some sort of pixel-to-window-size ratio for retina-like displays.
|
||||
ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues
|
||||
tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus
|
||||
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
|
||||
moving_within_opened_triangle = ImIsPointInTriangle(g.IO.MousePos, ta, tb, tc);
|
||||
//window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? 0x80008000 : 0x80000080); window->DrawList->PopClipRect(); // Debug
|
||||
}
|
||||
}
|
||||
|
||||
if (opened && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle)
|
||||
ClosePopup(label);
|
||||
want_open = (!opened && hovered);
|
||||
want_open = (!opened && hovered && !moving_within_opened_triangle) || (!opened && hovered && pressed);
|
||||
}
|
||||
else if (opened && pressed && menuset_opened) // menu-bar: click open menu to close
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user