Merge branch 'master' into navigation

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
docking
omar 7 years ago
commit db071184a0

@ -2393,18 +2393,17 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
window->DC.LastItemId = id; window->DC.LastItemId = id;
window->DC.LastItemRect = bb; window->DC.LastItemRect = bb;
window->DC.LastItemStatusFlags = 0;
// Clipping test // Clipping test
const bool is_clipped = IsClippedEx(bb, id, false); const bool is_clipped = IsClippedEx(bb, id, false);
if (is_clipped) if (is_clipped)
{
window->DC.LastItemRectHoveredRect = false;
return false; return false;
}
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
window->DC.LastItemRectHoveredRect = IsMouseHoveringRect(bb.Min, bb.Max); if (IsMouseHoveringRect(bb.Min, bb.Max))
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true; return true;
} }
@ -2419,7 +2418,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return IsItemFocused(); return IsItemFocused();
// Test for bounding box overlap, as updated as ItemAdd() // Test for bounding box overlap, as updated as ItemAdd()
if (!window->DC.LastItemRectHoveredRect) if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
return false; return false;
IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
@ -6051,8 +6050,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// After Begin() we fill the last item / hovered data using the title bar data. Make that a standard behavior (to allow usage of context menus on title bar only, etc.). // After Begin() we fill the last item / hovered data using the title bar data. Make that a standard behavior (to allow usage of context menus on title bar only, etc.).
window->DC.LastItemId = window->MoveId; window->DC.LastItemId = window->MoveId;
window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
window->DC.LastItemRect = title_bar_rect; window->DC.LastItemRect = title_bar_rect;
window->DC.LastItemRectHoveredRect = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false);
} }
// Inner clipping rectangle // Inner clipping rectangle
@ -7898,12 +7897,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// We vertically grow up to current line height up the typical widget height. // We vertically grow up to current line height up the typical widget height.
const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
if (display_frame) if (display_frame)
{ {
// Framed header expand a little outside the default padding // Framed header expand a little outside the default padding
bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
} }
const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
@ -7912,7 +7911,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
// (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not)
const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y);
bool is_open = TreeNodeBehaviorIsOpen(id, flags); bool is_open = TreeNodeBehaviorIsOpen(id, flags);
// Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
@ -7921,7 +7920,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavCloseFromChild) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavCloseFromChild) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
window->DC.TreeDepthMayCloseOnPop |= (1 << window->DC.TreeDepth); window->DC.TreeDepthMayCloseOnPop |= (1 << window->DC.TreeDepth);
if (!ItemAdd(interact_bb, id)) bool item_add = ItemAdd(interact_bb, id);
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
window->DC.LastItemDisplayRect = frame_bb;
if (!item_add)
{ {
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id); TreePushRawID(id);
@ -7976,25 +7979,25 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// Render // Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, text_base_offset_y); const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y);
if (display_frame) if (display_frame)
{ {
// Framed type // Framed type
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin);
RenderTriangle(bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); RenderTriangle(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
if (g.LogEnabled) if (g.LogEnabled)
{ {
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
const char log_prefix[] = "\n##"; const char log_prefix[] = "\n##";
const char log_suffix[] = "##"; const char log_suffix[] = "##";
LogRenderedText(&text_pos, log_prefix, log_prefix+3); LogRenderedText(&text_pos, log_prefix, log_prefix+3);
RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
LogRenderedText(&text_pos, log_suffix+1, log_suffix+3); LogRenderedText(&text_pos, log_suffix+1, log_suffix+3);
} }
else else
{ {
RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
} }
} }
else else
@ -8002,13 +8005,14 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// Unframed typed for tree nodes // Unframed typed for tree nodes
if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) if (hovered || (flags & ImGuiTreeNodeFlags_Selected))
{ {
RenderFrame(bb.Min, bb.Max, col, false); RenderFrame(frame_bb.Min, frame_bb.Max, col, false);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin);
} }
if (flags & ImGuiTreeNodeFlags_Bullet) if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));
else if (!(flags & ImGuiTreeNodeFlags_Leaf)) else if (!(flags & ImGuiTreeNodeFlags_Leaf))
RenderTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); RenderTriangle(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
if (g.LogEnabled) if (g.LogEnabled)
LogRenderedText(&text_pos, ">"); LogRenderedText(&text_pos, ">");
RenderText(text_pos, label, label_end, false); RenderText(text_pos, label, label_end, false);
@ -10792,7 +10796,7 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
window->DC.LastItemRect = bb; window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
BeginGroup(); BeginGroup();
if (label_size.x > 0) if (label_size.x > 0)
@ -11600,7 +11604,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
EndGroup(); EndGroup();
// Drag and Drop Target // Drag and Drop Target
if (window->DC.LastItemRectHoveredRect && BeginDragDropTarget()) // NB: The LastItemRectHoveredRect test is merely an optional micro-optimization if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && BeginDragDropTarget()) // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
{ {
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
{ {
@ -12021,9 +12025,9 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
bool add = ItemAdd(bb, id); bool item_add = ItemAdd(bb, id);
window->DC.ItemFlags = item_flags_backup; window->DC.ItemFlags = item_flags_backup;
if (!add) if (!item_add)
return false; return false;
bool hovered, held; bool hovered, held;
@ -12666,7 +12670,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button)
// We build a throwaway ID based on current ID stack + relative AABB of items in window. // We build a throwaway ID based on current ID stack + relative AABB of items in window.
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
bool is_hovered = window->DC.LastItemRectHoveredRect; bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0;
if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
return false; return false;
source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
@ -12717,7 +12721,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button)
} }
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
window->DC.LastItemRectHoveredRect = false; window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true; return true;
} }
@ -12814,18 +12818,19 @@ bool ImGui::BeginDragDropTarget()
return false; return false;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!window->DC.LastItemRectHoveredRect) if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
return false; return false;
if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
return false; return false;
const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
ImGuiID id = window->DC.LastItemId; ImGuiID id = window->DC.LastItemId;
if (id == 0) if (id == 0)
id = window->GetIDFromRectangle(window->DC.LastItemRect); id = window->GetIDFromRectangle(display_rect);
if (g.DragDropPayload.SourceId == id) if (g.DragDropPayload.SourceId == id)
return false; return false;
g.DragDropTargetRect = window->DC.LastItemRect; g.DragDropTargetRect = display_rect;
g.DragDropTargetId = id; g.DragDropTargetId = id;
return true; return true;
} }

@ -46,6 +46,7 @@ struct ImGuiWindowSettings;
typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_
typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_
typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_
typedef int ImGuiItemStatusFlags; // flags: storage for DC.LastItemXXX // enum ImGuiItemStatusFlags_
typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_ typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_
typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_ typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_
typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_
@ -220,6 +221,13 @@ enum ImGuiSeparatorFlags_
ImGuiSeparatorFlags_Vertical = 1 << 1 ImGuiSeparatorFlags_Vertical = 1 << 1
}; };
// Storage for LastItem data
enum ImGuiItemStatusFlags_
{
ImGuiItemStatusFlags_HoveredRect = 1 << 0,
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1
};
// FIXME: this is in development, not exposed/functional as a generic feature yet. // FIXME: this is in development, not exposed/functional as a generic feature yet.
enum ImGuiLayoutType_ enum ImGuiLayoutType_
{ {
@ -795,6 +803,7 @@ struct ImGuiContext
}; };
// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). // Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
// This is going to be exposed in imgui.h when stabilized enough.
enum ImGuiItemFlags_ enum ImGuiItemFlags_
{ {
ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true
@ -822,8 +831,9 @@ struct IMGUI_API ImGuiDrawContext
int TreeDepth; int TreeDepth;
ImU32 TreeDepthMayCloseOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 ImU32 TreeDepthMayCloseOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31
ImGuiID LastItemId; ImGuiID LastItemId;
ImRect LastItemRect; ImGuiItemStatusFlags LastItemStatusFlags;
bool LastItemRectHoveredRect; ImRect LastItemRect; // Interaction rect
ImRect LastItemDisplayRect; // End-user display rect (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect)
bool NavHideHighlightOneFrame; bool NavHideHighlightOneFrame;
bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f)
int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
@ -861,8 +871,8 @@ struct IMGUI_API ImGuiDrawContext
TreeDepth = 0; TreeDepth = 0;
TreeDepthMayCloseOnPop = 0x00; TreeDepthMayCloseOnPop = 0x00;
LastItemId = 0; LastItemId = 0;
LastItemRect = ImRect(); LastItemStatusFlags = 0;
LastItemRectHoveredRect = false; LastItemRect = LastItemDisplayRect = ImRect();
NavHideHighlightOneFrame = false; NavHideHighlightOneFrame = false;
NavHasScroll = false; NavHasScroll = false;
NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerActiveMask = NavLayerActiveMaskNext = 0x00;
@ -983,12 +993,13 @@ public:
struct ImGuiItemHoveredDataBackup struct ImGuiItemHoveredDataBackup
{ {
ImGuiID LastItemId; ImGuiID LastItemId;
ImGuiItemStatusFlags LastItemStatusFlags;
ImRect LastItemRect; ImRect LastItemRect;
bool LastItemRectHoveredRect; ImRect LastItemDisplayRect;
ImGuiItemHoveredDataBackup() { Backup(); } ImGuiItemHoveredDataBackup() { Backup(); }
void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; }
void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

Loading…
Cancel
Save