Updated ImGui.

This commit is contained in:
Бранимир Караџић 2019-04-25 21:58:49 -07:00
parent fcfc26c482
commit 62ea70c449
4 changed files with 89 additions and 73 deletions

View File

@ -3517,8 +3517,8 @@ void ImGui::NewFrame()
g.ActiveIdIsAlive = 0;
g.ActiveIdPreviousFrameIsAlive = false;
g.ActiveIdIsJustActivated = false;
if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
g.ScalarAsInputTextId = 0;
if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId)
g.TempInputTextId = 0;
// Drag and drop
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
@ -4069,7 +4069,7 @@ static void FindHoveredWindow()
// Using the clipped AABB, a child window will typically be clipped by its parent (not always)
ImRect bb(window->OuterRectClipped);
if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize))
if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
bb.Expand(padding_regular);
else
bb.Expand(padding_for_resize_from_edges);
@ -6008,7 +6008,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
*pvar = val;
return;
}
IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.
IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!");
}
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
@ -6022,7 +6022,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
*pvar = val;
return;
}
IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.
IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!");
}
void ImGui::PopStyleVar(int count)
@ -6684,6 +6684,13 @@ void ImGui::PushID(int int_id)
window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
}
// Push a given id value ignoring the ID stack as a seed.
void ImGui::PushOverrideID(ImGuiID id)
{
ImGuiWindow* window = GImGui->CurrentWindow;
window->IDStack.push_back(id);
}
void ImGui::PopID()
{
ImGuiWindow* window = GImGui->CurrentWindow;

View File

@ -938,7 +938,7 @@ struct ImGuiContext
// Widget state
ImGuiInputTextState InputTextState;
ImFont InputTextPasswordFont;
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
ImVec4 ColorPickerRef;
bool DragCurrentAccumDirty;
@ -1075,7 +1075,7 @@ struct ImGuiContext
CurrentTabBar = NULL;
ScalarAsInputTextId = 0;
TempInputTextId = 0;
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f;
@ -1431,6 +1431,7 @@ namespace ImGui
IMGUI_API void SetHoveredID(ImGuiID id);
IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void MarkItemEdited(ImGuiID id);
IMGUI_API void PushOverrideID(ImGuiID id);
// Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
@ -1546,7 +1547,7 @@ namespace ImGui
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);
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 SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API void TreePushRawID(ImGuiID id);
IMGUI_API void TreePushOverrideID(ImGuiID id);
// 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).
@ -1558,7 +1559,8 @@ namespace ImGui
// InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format);
IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format);
inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); }
// Color
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);

View File

@ -1989,8 +1989,6 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
if (!ItemAdd(total_bb, id, &frame_bb))
return false;
const bool hovered = ItemHoverable(frame_bb, id);
// Default format string when passing NULL
// Patch old "%.0f" format string to use "%d", read function comments for more details.
IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
@ -2000,37 +1998,40 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
format = PatchFormatStringFloatToInt(format);
// Tabbing or CTRL-clicking on Drag turns it into an input box
bool start_text_input = false;
const bool focus_requested = FocusableItemRegister(window, id);
if (focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
const bool hovered = ItemHoverable(frame_bb, id);
bool temp_input_is_active = TempInputTextIsActive(id);
bool temp_input_start = false;
if (!temp_input_is_active)
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
const bool focus_requested = FocusableItemRegister(window, id);
const bool clicked = (hovered && g.IO.MouseClicked[0]);
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id)
{
temp_input_start = true;
FocusableItemUnregister(window);
}
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
{
window->DC.CursorPos = frame_bb.Min;
FocusableItemUnregister(window);
return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
}
// Actual drag behavior
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
if (value_changed)
MarkItemEdited(id);
if (temp_input_is_active || temp_input_start)
return TempInputTextScalar(frame_bb, id, label, data_type, v, format);
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
// Drag behavior
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
if (value_changed)
MarkItemEdited(id);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
@ -2457,27 +2458,28 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
format = PatchFormatStringFloatToInt(format);
// Tabbing or CTRL-clicking on Slider turns it into an input box
bool start_text_input = false;
const bool focus_requested = FocusableItemRegister(window, id);
const bool hovered = ItemHoverable(frame_bb, id);
if (focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
bool temp_input_is_active = TempInputTextIsActive(id);
bool temp_input_start = false;
if (!temp_input_is_active)
{
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
const bool focus_requested = FocusableItemRegister(window, id);
const bool clicked = (hovered && g.IO.MouseClicked[0]);
if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id)
{
temp_input_start = true;
FocusableItemUnregister(window);
}
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
{
window->DC.CursorPos = frame_bb.Min;
FocusableItemUnregister(window);
return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
}
if (temp_input_is_active || temp_input_start)
return TempInputTextScalar(frame_bb, id, label, data_type, v, format);
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
@ -2663,7 +2665,7 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
// - ImParseFormatFindEnd() [Internal]
// - ImParseFormatTrimDecorations() [Internal]
// - ImParseFormatPrecision() [Internal]
// - InputScalarAsWidgetReplacement() [Internal]
// - TempInputTextScalar() [Internal]
// - InputScalar()
// - InputScalarN()
// - InputFloat()
@ -2749,16 +2751,16 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
return (precision == INT_MAX) ? default_precision : precision;
}
// Create text input in place of an active drag/slider (used when doing a CTRL+Click on drag/slider widgets)
// Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
// FIXME: Facilitate using this in variety of other situations.
bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format)
bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format)
{
IM_UNUSED(id);
ImGuiContext& g = *GImGui;
// On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id.
// On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
// We clear ActiveID on the first frame to allow the InputText() taking it back.
if (g.ScalarAsInputTextId == 0)
const bool init = (g.TempInputTextId != id);
if (init)
ClearActiveID();
char fmt_buf[32];
@ -2766,13 +2768,15 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format);
ImStrTrimBlanks(data_buf);
g.CurrentWindow->DC.CursorPos = bb.Min;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
if (g.ScalarAsInputTextId == 0)
if (init)
{
// First frame we started displaying the InputText widget, we expect it to take the active id.
IM_ASSERT(g.ActiveId == id);
g.ScalarAsInputTextId = g.ActiveId;
g.TempInputTextId = g.ActiveId;
}
if (value_changed)
return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL);
@ -5097,7 +5101,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (!item_add)
{
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id);
TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open;
}
@ -5201,7 +5205,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
}
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id);
TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open;
}
@ -5222,7 +5226,7 @@ void ImGui::TreePush(const void* ptr_id)
PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
}
void ImGui::TreePushRawID(ImGuiID id)
void ImGui::TreePushOverrideID(ImGuiID id)
{
ImGuiWindow* window = GetCurrentWindow();
Indent();
@ -5420,7 +5424,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bb.Max.x -= (GetContentRegionMax().x - max_x);
}
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
RenderTextClipped(bb_inner.Min, bb_inner.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
@ -5892,10 +5896,11 @@ void ImGui::EndMenuBar()
{
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check
const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check
FocusWindow(window);
SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]);
g.NavLayer = ImGuiNavLayer_Menu;
SetNavIDWithRectRel(window->NavLastIds[layer], layer, window->NavRectRel[layer]);
g.NavLayer = layer;
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
NavMoveRequestCancel();
@ -5945,7 +5950,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x;
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
PopStyleVar();
@ -6089,7 +6094,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
// Note that in this situation we render neither the shortcut neither the selected tick mark
float w = label_size.x;
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
PopStyleVar();
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -6225,7 +6230,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
return false;
if ((flags & ImGuiTabBarFlags_DockNode) == 0)
window->IDStack.push_back(tab_bar->ID);
PushOverrideID(tab_bar->ID);
// Add to stack
g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
@ -6677,7 +6682,8 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
{
ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems)
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return false;
ImGuiTabBar* tab_bar = g.CurrentTabBar;
@ -6690,7 +6696,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
{
ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
g.CurrentWindow->IDStack.push_back(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
}
return ret;
}
@ -6698,7 +6704,8 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
void ImGui::EndTabItem()
{
ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems)
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return;
ImGuiTabBar* tab_bar = g.CurrentTabBar;
@ -6710,7 +6717,7 @@ void ImGui::EndTabItem()
IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
g.CurrentWindow->IDStack.pop_back();
window->IDStack.pop_back();
}
bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)

View File

@ -192,15 +192,15 @@ bool RangeSliderFloat(const char* label, float* v1, float* v2, float v_min, floa
if (tab_focus_requested || g.IO.KeyCtrl)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
g.TempInputTextId = 0;
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
if (start_text_input || (g.ActiveId == id && g.TempInputTextId == id))
{
char fmt[64];
snprintf(fmt, 64, "%%.%df", decimal_precision);
return InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_Float, v1, fmt);
return TempInputTextScalar(frame_bb, id, label, ImGuiDataType_Float, v1, fmt);
}
ItemSize(total_bb, style.FramePadding.y);