Updated ImGui.

This commit is contained in:
Branimir Karadžić 2016-05-01 16:46:36 -07:00
parent 8658890d37
commit 034fd7c437
5 changed files with 327 additions and 154 deletions

View File

@ -152,6 +152,7 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
- 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
- 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
- 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
@ -552,6 +553,7 @@
- shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus)
!- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing
- keyboard: full keyboard navigation and focus. (#323)
- focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622)
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- input: rework IO system to be able to pass actual ordered/timestamped events.
- input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style).
@ -708,7 +710,7 @@ ImGuiStyle::ImGuiStyle()
ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node
IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
@ -1722,29 +1724,22 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
ImGuiWindow* window = GetCurrentWindow();
window->DC.LastItemID = id ? *id : 0;
window->DC.LastItemRect = bb;
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
if (IsClippedEx(bb, id, false))
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
return false;
}
// This is a sensible default, but widgets are free to override it after calling ItemAdd()
ImGuiState& g = *GImGui;
if (IsMouseHoveringRect(bb.Min, bb.Max))
{
// Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background)
// Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background)
// So that clicking on items with no active id such as Text() still returns true with IsItemHovered()
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
else
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
}
return true;
}
@ -1755,14 +1750,13 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when
ImGuiWindow* window = GetCurrentWindowRead();
if (!bb.Overlaps(window->ClipRect))
{
if (!id || *id != GImGui->ActiveId)
if (clip_even_when_logged || !g.LogEnabled)
return true;
}
return false;
}
// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic.
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
@ -1770,7 +1764,7 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiWindow* window = GetCurrentWindowRead();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
@ -2373,6 +2367,7 @@ static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiW
}
}
// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
{
ImGuiWindow* window = GetCurrentWindow();
@ -2748,6 +2743,12 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool
window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text));
}
void ImGui::RenderBullet(ImVec2 pos)
{
ImGuiWindow* window = GetCurrentWindow();
window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
}
void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col)
{
ImGuiState& g = *GImGui;
@ -3062,6 +3063,11 @@ bool ImGui::IsItemActive()
return false;
}
bool ImGui::IsItemClicked(int mouse_button)
{
return IsMouseClicked(mouse_button) && IsItemHovered();
}
bool ImGui::IsAnyItemHovered()
{
return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0;
@ -4123,11 +4129,11 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
// Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior.
const ImRect title_bar_rect = window->TitleBarRect();
const float border_size = window->BorderSize;
ImRect clip_rect;
clip_rect.Min.x = title_bar_rect.Min.x + ImMax(border_size, (float)(int)(window->WindowPadding.x*0.5f));
clip_rect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + border_size;
clip_rect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, (float)(int)(window->WindowPadding.x*0.5f));
clip_rect.Max.y = window->Pos.y + window->Size.y - border_size - window->ScrollbarSizes.y;
ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f)));
clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size);
clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f)));
clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size);
PushClipRect(clip_rect.Min, clip_rect.Max, true);
// Clear 'accessed' flag last thing
@ -4587,15 +4593,19 @@ bool ImGui::IsWindowFocused()
bool ImGui::IsRootWindowFocused()
{
ImGuiState& g = *GImGui;
ImGuiWindow* root_window = g.CurrentWindow->RootWindow;
return g.FocusedWindow == root_window;
return g.FocusedWindow == g.CurrentWindow->RootWindow;
}
bool ImGui::IsRootWindowOrAnyChildFocused()
{
ImGuiState& g = *GImGui;
ImGuiWindow* root_window = g.CurrentWindow->RootWindow;
return g.FocusedWindow && g.FocusedWindow->RootWindow == root_window;
return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow;
}
bool ImGui::IsRootWindowOrAnyChildHovered()
{
ImGuiState& g = *GImGui;
return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow);
}
float ImGui::GetWindowWidth()
@ -5263,39 +5273,34 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
return false;
}
if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0)
flags |= ImGuiButtonFlags_PressedOnClickRelease;
bool pressed = false;
const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
if (hovered)
{
SetHoveredID(id);
if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
{
if (g.IO.MouseDoubleClicked[0] && (flags & ImGuiButtonFlags_PressedOnDoubleClick))
if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) // Most common type
{
pressed = true;
}
else if (g.IO.MouseClicked[0])
{
if (flags & ImGuiButtonFlags_PressedOnClick)
{
pressed = true;
SetActiveID(0);
}
else
{
SetActiveID(id, window);
}
SetActiveID(id, window); // Hold on ID
FocusWindow(window);
}
else if (g.IO.MouseReleased[0] && (flags & ImGuiButtonFlags_PressedOnRelease))
if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]))
{
pressed = true;
SetActiveID(0);
FocusWindow(window);
}
if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0])
{
pressed = true;
SetActiveID(0);
}
else if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true))
{
if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true))
pressed = true;
}
}
}
@ -5308,12 +5313,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
}
else
{
if (hovered)
if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))
pressed = true;
SetActiveID(0);
}
}
// AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
hovered = pressed = held = false;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
@ -5594,6 +5603,9 @@ void ImGui::LogButtons()
bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
{
if (flags & ImGuiTreeNodeFlags_AlwaysOpen)
return true;
// We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions)
ImGuiState& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
@ -5630,14 +5642,13 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
// When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
// NB- If we are above max depth we still allow manually opened nodes to be logged.
if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoExpandOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
opened = true;
return opened;
}
// FIXME: Split into CollapsingHeader(label, default_open?) and TreeNodeBehavior(label), obsolete the 4 parameters function.
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
@ -5645,20 +5656,16 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
IM_ASSERT(str_id != NULL || label != NULL);
if (str_id == NULL)
str_id = label;
if (label == NULL)
label = str_id;
const bool label_hide_text_after_double_hash = (label == str_id); // Only search and hide text after ## if we have passed label and ID separately, otherwise allow "##" within format string.
const ImGuiID id = window->GetID(str_id);
const ImVec2 label_size = CalcTextSize(label, NULL, label_hide_text_after_double_hash);
if (!label_end)
label_end = FindRenderedTextEnd(label);
const ImVec2 label_size = CalcTextSize(label, label_end, false);
// We vertically grow up to current line height up the typical widget height.
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it
const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.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));
if (display_frame)
{
@ -5667,28 +5674,49 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
}
const float collapser_width = g.FontSize + (display_frame ? padding.x*2 : padding.x);
const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
// 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 we want 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);
bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
bool opened = TreeNodeBehaviorIsOpened(id, flags);
if (!ItemAdd(interact_bb, &id))
return opened;
bool hovered, held;
bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, ImGuiButtonFlags_NoKeyModifiers);
if (pressed)
{
opened = !opened;
window->DC.StateStorage->SetInt(id, opened);
if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id);
return opened;
}
// Flags that affects opening behavior:
// - 0(default) ..................... single-click anywhere to open
// - OpenOnDoubleClick .............. double-click anywhere to open
// - OpenOnArrow .................... single-click on arrow to open
// - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open
ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0);
if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0);
bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
if (pressed && !(flags & ImGuiTreeNodeFlags_AlwaysOpen))
{
bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick));
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y));
if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
toggled |= g.IO.MouseDoubleClicked[0];
if (toggled)
{
opened = !opened;
window->DC.StateStorage->SetInt(id, opened);
}
}
if (flags & ImGuiTreeNodeFlags_AllowOverlapMode)
SetItemAllowOverlap();
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
const ImVec2 text_pos = bb.Min + padding + ImVec2(collapser_width, text_base_offset_y);
const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, padding.y + text_base_offset_y);
if (display_frame)
{
// Framed type
@ -5700,48 +5728,122 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
const char log_prefix[] = "\n##";
const char log_suffix[] = "##";
LogRenderedText(text_pos, log_prefix, log_prefix+3);
RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size);
LogRenderedText(text_pos, log_suffix+1, log_suffix+3);
}
else
{
RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size);
}
}
else
{
// Unframed typed for tree nodes
if (hovered)
if (hovered || (flags & ImGuiTreeNodeFlags_Selected))
RenderFrame(bb.Min, bb.Max, col, false);
RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false);
if (flags & ImGuiTreeNodeFlags_AlwaysOpen)
RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));
else
RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false);
if (g.LogEnabled)
LogRenderedText(text_pos, ">");
RenderText(text_pos, label, NULL, label_hide_text_after_double_hash);
RenderText(text_pos, label, label_end, false);
}
if (opened && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id);
return opened;
}
bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label);
}
bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
if (p_open && !*p_open)
return false;
ImGuiID id = window->GetID(label);
bool opened = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label);
if (p_open)
{
// Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
ImGuiState& g = *GImGui;
float button_sz = g.FontSize * 0.5f;
if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(window->DC.LastItemRect.Max.x - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz))
*p_open = false;
}
return opened;
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
}
bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiState& g = *GImGui;
ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
if (!str_id || !str_id[0])
str_id = fmt;
const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
}
ImGui::PushID(str_id);
const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false);
ImGui::PopID();
bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
if (opened)
ImGui::TreePush(str_id);
ImGuiState& g = *GImGui;
const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
}
bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
{
return TreeNodeExV(str_id, 0, fmt, args);
}
bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
{
return TreeNodeExV(ptr_id, 0, fmt, args);
}
bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
bool opened = TreeNodeExV(str_id, flags, fmt, args);
va_end(args);
return opened;
}
bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
bool opened = TreeNodeExV(ptr_id, flags, fmt, args);
va_end(args);
return opened;
}
@ -5749,31 +5851,8 @@ bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
bool s = TreeNodeV(str_id, fmt, args);
bool opened = TreeNodeExV(str_id, 0, fmt, args);
va_end(args);
return s;
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiState& g = *GImGui;
ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
if (!ptr_id)
ptr_id = fmt;
ImGui::PushID(ptr_id);
const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false);
ImGui::PopID();
if (opened)
ImGui::TreePush(ptr_id);
return opened;
}
@ -5781,14 +5860,29 @@ bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
bool s = TreeNodeV(ptr_id, fmt, args);
bool opened = TreeNodeExV(ptr_id, 0, fmt, args);
va_end(args);
return s;
return opened;
}
bool ImGui::TreeNode(const char* str_label_id)
bool ImGui::TreeNode(const char* label)
{
return TreeNode(str_label_id, "%s", str_label_id);
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
}
float ImGui::GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags)
{
ImGuiState& g = *GImGui;
float off_from_start;
if (flags & ImGuiTreeNodeFlags_Framed)
off_from_start = g.FontSize + (g.Style.FramePadding.x * 3.0f) - ((float)(int)(g.CurrentWindow->WindowPadding.x*0.5f) - 1);
else
off_from_start = g.FontSize + (g.Style.FramePadding.x * 2.0f);
return off_from_start;
}
void ImGui::SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond)
@ -5861,12 +5955,9 @@ void ImGui::Bullet()
return;
}
// Render
const float bullet_size = g.FontSize*0.15f;
window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text));
// Stay on same line
ImGui::SameLine(0, style.FramePadding.x*2);
// Render and stay on same line
RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
SameLine(0, style.FramePadding.x*2);
}
// Text with a little bullet aligned to the typical tree node.
@ -5890,8 +5981,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
return;
// Render
const float bullet_size = g.FontSize*0.15f;
window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), bullet_size, GetColorU32(ImGuiCol_Text));
RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end);
}
@ -8222,7 +8312,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick;
if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease;
if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled;
if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick;
if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
bool hovered, held;
bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, button_flags);
if (flags & ImGuiSelectableFlags_Disabled)
@ -8429,7 +8519,7 @@ bool ImGui::BeginMenuBar()
ImGui::BeginGroup(); // Save position
ImGui::PushID("##menubar");
ImRect rect = window->MenuBarRect();
PushClipRect(ImVec2(rect.Min.x, rect.Min.y + window->BorderSize), ImVec2(rect.Max.x, rect.Max.y), false);
PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false);
window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y);
window->DC.LayoutType = ImGuiLayoutType_Horizontal;
window->DC.MenuBarAppending = true;
@ -8992,7 +9082,7 @@ float ImGui::GetColumnWidth(int column_index)
if (column_index < 0)
column_index = window->DC.ColumnsCurrent;
const float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index);
float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index);
return w;
}
@ -9002,8 +9092,8 @@ static void PushColumnClipRect(int column_index)
if (column_index < 0)
column_index = window->DC.ColumnsCurrent;
const float x1 = window->Pos.x + ImGui::GetColumnOffset(column_index) - 1;
const float x2 = window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1;
float x1 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index) - 1.0f);
float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1.0f);
ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true);
}
@ -9131,6 +9221,14 @@ void ImGui::TreePush(const void* ptr_id)
PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
}
void ImGui::TreePushRawID(ImGuiID id)
{
ImGuiWindow* window = GetCurrentWindow();
ImGui::Indent();
window->DC.TreeDepth++;
window->IDStack.push_back(id);
}
void ImGui::TreePop()
{
ImGuiWindow* window = GetCurrentWindow();
@ -9349,8 +9447,8 @@ void ImGui::ShowMetricsWindow(bool* opened)
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)
vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos);
clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, ImColor(255,255,0));
vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, ImColor(255,0,255));
clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255));
vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255));
}
if (!draw_opened)
continue;
@ -9366,7 +9464,7 @@ void ImGui::ShowMetricsWindow(bool* opened)
}
ImGui::Selectable(buf, false);
if (ImGui::IsItemHovered())
overlay_draw_list->AddPolyline(triangles_pos, 3, ImColor(255,255,0), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle
overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle
}
ImGui::TreePop();
}

View File

@ -70,6 +70,7 @@ typedef int ImGuiWindowFlags; // window flags for Begin*() // e
typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_
typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_
typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_
typedef int ImGuiTreeNodeFlags; // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_
typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data);
// Others helpers at bottom of the file:
@ -251,7 +252,6 @@ namespace ImGui
IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size);
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding
IMGUI_API bool CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false);
IMGUI_API bool Checkbox(const char* label, bool* v);
IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
IMGUI_API bool RadioButton(const char* label, bool active);
@ -307,15 +307,23 @@ namespace ImGui
IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f");
// Widgets: Trees
IMGUI_API bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop().
IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop().
IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().
IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // "
IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // "
IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // "
IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose
IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0);
IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3);
IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3);
IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args);
IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args);
IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layout purpose
IMGUI_API void TreePush(const void* ptr_id = NULL); // "
IMGUI_API void TreePop();
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened.
IMGUI_API float GetTreeNodeToLabelSpacing(ImGuiTreeNodeFlags flags = 0); // return horizontal distance between cursor and text label due to collapsing node. == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode
IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. user doesn't have to call TreePop().
IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header
// Widgets: Selectable / Lists
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
@ -376,6 +384,7 @@ namespace ImGui
IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse?
IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this
IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false)
IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on)
IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.)
IMGUI_API bool IsAnyItemHovered();
IMGUI_API bool IsAnyItemActive();
@ -385,8 +394,9 @@ namespace ImGui
IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others)
IMGUI_API bool IsWindowFocused(); // is current window focused
IMGUI_API bool IsRootWindowFocused(); // is current root window focused (top parent window in case of child windows)
IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self)
IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused
IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)
IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle of given size starting from cursor pos is visible (not clipped). to perform coarse clipping on user's side (as an optimization)
IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window
IMGUI_API float GetTime();
@ -440,6 +450,7 @@ namespace ImGui
// Obsolete (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline bool CollapsingHeader(const char* label, const char* str_id, bool display_frame = true, bool default_open = false) { (void)str_id; (void)display_frame; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+
static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+
static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+
static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpened(open, 0); } // OBSOLETE 1.34+
@ -511,6 +522,24 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline()
};
// Flags for ImGui::TreeNode*(), ImGui::CollapsingHeader*()
enum ImGuiTreeNodeFlags_
{
ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader)
ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when opened (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be opened
ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open.
ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
//ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position
//ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just opened and contents is not visible
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog
};
// Flags for ImGui::Selectable()
enum ImGuiSelectableFlags_
{
@ -668,7 +697,7 @@ struct ImGuiStyle
ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns
float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar
float ScrollbarRounding; // Radius of grab corners for scrollbar

View File

@ -270,16 +270,65 @@ void ImGui::ShowTestWindow(bool* p_opened)
{
if (ImGui::TreeNode("Trees"))
{
for (int i = 0; i < 5; i++)
if (ImGui::TreeNode("Basic trees"))
{
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
for (int i = 0; i < 5; i++)
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
{
ImGui::Text("blah blah");
ImGui::SameLine();
if (ImGui::SmallButton("print")) printf("Child %d pressed", i);
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("With selectable nodes"))
{
ShowHelpMarker("Click to select, CTRL+Click to toggle, click on arrows to open");
static int selection_mask = 0x02; // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
int node_clicked = -1;
for (int i = 0; i < 6; i++)
{
ImGui::Text("blah blah");
ImGui::SameLine();
if (ImGui::SmallButton("print"))
printf("Child %d pressed", i);
ImGui::TreePop();
ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
if (i >= 3)
node_flags |= ImGuiTreeNodeFlags_AlwaysOpen;
bool opened = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i);
if (ImGui::IsItemClicked())
node_clicked = i;
if (opened)
{
ImGui::Text("Blah blah");
ImGui::Text("Blah blah");
ImGui::TreePop();
}
}
if (node_clicked != -1)
{
// Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
if (ImGui::GetIO().KeyCtrl)
selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
else
selection_mask = (1 << node_clicked); // Click to single-select
}
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Collapsing Headers"))
{
static bool closable_group = true;
if (ImGui::CollapsingHeader("Header"))
{
ImGui::Checkbox("Enable extra group", &closable_group);
for (int i = 0; i < 5; i++)
ImGui::Text("Some content %d", i);
}
if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
{
for (int i = 0; i < 5; i++)
ImGui::Text("More content %d", i);
}
ImGui::TreePop();
}

View File

@ -229,10 +229,6 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_
}
cr.z = ImMax(cr.x, cr.z);
cr.w = ImMax(cr.y, cr.w);
cr.x = (float)(int)(cr.x + 0.5f); // Round (expecting to round down). Ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
cr.y = (float)(int)(cr.y + 0.5f);
cr.z = (float)(int)(cr.z + 0.5f);
cr.w = (float)(int)(cr.w + 0.5f);
_ClipRectStack.push_back(cr);
UpdateClipRect();

View File

@ -135,6 +135,7 @@ 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 inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
static inline float ImFloor(float f) { return (float)(int)f; }
static inline ImVec2 ImFloor(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
@ -153,20 +154,16 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {}
enum ImGuiButtonFlags_
{
ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat
ImGuiButtonFlags_PressedOnClick = 1 << 1, // return pressed on click (default requires click+release)
ImGuiButtonFlags_PressedOnRelease = 1 << 2, // return pressed on release (default requires click+release)
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 3, // return pressed on double-click (default requires click+release)
ImGuiButtonFlags_FlattenChilds = 1 << 4, // allow interaction even if a child window is overlapping
ImGuiButtonFlags_DontClosePopups = 1 << 5, // disable automatically closing parent popup on press
ImGuiButtonFlags_Disabled = 1 << 6, // disable interaction
ImGuiButtonFlags_AlignTextBaseLine = 1 << 7, // vertically align button to match text baseline - ButtonEx() only
ImGuiButtonFlags_NoKeyModifiers = 1 << 8 // disable interaction if a key modifier is held
};
enum ImGuiTreeNodeFlags_
{
ImGuiTreeNodeFlags_DefaultOpen = 1 << 0,
ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1
ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set)
ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release)
ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release)
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release)
ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping
ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press
ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction
ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only
ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held
ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable
};
enum ImGuiSliderFlags_
@ -702,12 +699,14 @@ namespace ImGui
inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
// NB: All position are in absolute pixels coordinates (not window coordinates)
// FIXME: Refactor all RenderText* functions into one.
// FIXME: All those functions are a mess and needs to be refactored into something decent. Avoid use outside of imgui.cpp!
// We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers.
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool opened, float scale = 1.0f, bool shadow = false);
IMGUI_API void RenderBullet(ImVec2 pos);
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col);
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
@ -729,7 +728,9 @@ namespace ImGui
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API void TreePushRawID(ImGuiID id);
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);