mirror of
https://github.com/wolfpld/tracy.git
synced 2025-03-20 07:40:02 +08:00
Bump ImGui do 1.85 + docking.
This commit is contained in:
+151
-123
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.84
|
||||
// dear imgui, v1.85
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -152,9 +152,13 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(text != NULL);
|
||||
|
||||
// Accept null ranges
|
||||
if (text == text_end)
|
||||
text = text_end = "";
|
||||
|
||||
// Calculate length
|
||||
const char* text_begin = text;
|
||||
if (text_end == NULL)
|
||||
text_end = text + strlen(text); // FIXME-OPT
|
||||
@@ -201,7 +205,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
|
||||
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
|
||||
while (line < text_end)
|
||||
{
|
||||
if (IsClippedEx(line_rect, 0, false))
|
||||
if (IsClippedEx(line_rect, 0))
|
||||
break;
|
||||
|
||||
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
|
||||
@@ -269,6 +273,7 @@ void ImGui::TextV(const char* fmt, va_list args)
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
// FIXME-OPT: Handle the %s shortcut?
|
||||
ImGuiContext& g = *GImGui;
|
||||
const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
|
||||
@@ -566,6 +571,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
ClearActiveID();
|
||||
else
|
||||
SetActiveID(id, window); // Hold on ID
|
||||
if (!(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
SetFocusID(id, window);
|
||||
g.ActiveIdMouseButton = mouse_button_clicked;
|
||||
FocusWindow(window);
|
||||
}
|
||||
@@ -576,6 +583,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay;
|
||||
if (!has_repeated_at_least_once)
|
||||
pressed = true;
|
||||
if (!(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
SetFocusID(id, window);
|
||||
ClearActiveID();
|
||||
}
|
||||
|
||||
@@ -600,13 +609,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
bool nav_activated_by_code = (g.NavActivateId == id);
|
||||
bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed);
|
||||
if (nav_activated_by_code || nav_activated_by_inputs)
|
||||
pressed = true;
|
||||
if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id)
|
||||
{
|
||||
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
|
||||
g.NavActivateId = id; // This is so SetActiveId assign a Nav source
|
||||
pressed = true;
|
||||
SetActiveID(id, window);
|
||||
if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
g.ActiveIdSource = ImGuiInputSource_Nav;
|
||||
if (!(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
SetFocusID(id, window);
|
||||
}
|
||||
}
|
||||
@@ -1583,7 +1591,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
||||
const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
|
||||
bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
|
||||
if ((pressed || g.NavActivateId == id) && !popup_open)
|
||||
if (pressed && !popup_open)
|
||||
{
|
||||
OpenPopupEx(popup_id, ImGuiPopupFlags_None);
|
||||
popup_open = true;
|
||||
@@ -1797,7 +1805,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
|
||||
bool value_changed = false;
|
||||
for (int i = 0; i < items_count; i++)
|
||||
{
|
||||
PushID((void*)(intptr_t)i);
|
||||
PushID(i);
|
||||
const bool item_selected = (i == *current_item);
|
||||
const char* item_text;
|
||||
if (!items_getter(data, i, &item_text))
|
||||
@@ -2391,7 +2399,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
|
||||
return false;
|
||||
|
||||
// Default format string when passing NULL
|
||||
@@ -2405,24 +2413,26 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
|
||||
if (!temp_input_is_active)
|
||||
{
|
||||
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0;
|
||||
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
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)
|
||||
if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
|
||||
{
|
||||
SetActiveID(id, window);
|
||||
SetFocusID(id, window);
|
||||
FocusWindow(window);
|
||||
g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
|
||||
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id))
|
||||
temp_input_is_active = true;
|
||||
if (temp_input_allowed)
|
||||
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
|
||||
temp_input_is_active = true;
|
||||
}
|
||||
|
||||
// Experimental: simple click (without moving) turns Drag into an InputText
|
||||
// FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings.
|
||||
if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
|
||||
if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
|
||||
{
|
||||
g.NavInputId = id;
|
||||
g.NavActivateId = g.NavActivateInputId = id;
|
||||
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
|
||||
temp_input_is_active = true;
|
||||
}
|
||||
}
|
||||
@@ -3007,7 +3017,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
|
||||
return false;
|
||||
|
||||
// Default format string when passing NULL
|
||||
@@ -3021,15 +3031,15 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
|
||||
if (!temp_input_is_active)
|
||||
{
|
||||
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0;
|
||||
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
const bool clicked = (hovered && g.IO.MouseClicked[0]);
|
||||
if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
|
||||
if (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id)
|
||||
{
|
||||
SetActiveID(id, window);
|
||||
SetFocusID(id, window);
|
||||
FocusWindow(window);
|
||||
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
|
||||
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id))
|
||||
if (temp_input_allowed && (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id))
|
||||
temp_input_is_active = true;
|
||||
}
|
||||
}
|
||||
@@ -3181,7 +3191,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
format = PatchFormatStringFloatToInt(format);
|
||||
|
||||
const bool hovered = ItemHoverable(frame_bb, id);
|
||||
if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id)
|
||||
if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavActivateInputId == id)
|
||||
{
|
||||
SetActiveID(id, window);
|
||||
SetFocusID(id, window);
|
||||
@@ -3445,7 +3455,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
style.FramePadding.x = style.FramePadding.y;
|
||||
ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups;
|
||||
if (flags & ImGuiInputTextFlags_ReadOnly)
|
||||
BeginDisabled(true);
|
||||
BeginDisabled();
|
||||
SameLine(0, style.ItemInnerSpacing.x);
|
||||
if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
|
||||
{
|
||||
@@ -3975,15 +3985,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImGuiItemStatusFlags item_status_flags = 0;
|
||||
if (is_multiline)
|
||||
{
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
|
||||
ImVec2 backup_pos = window->DC.CursorPos;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
||||
{
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
EndGroup();
|
||||
return false;
|
||||
}
|
||||
item_status_flags = g.LastItemData.StatusFlags;
|
||||
window->DC.CursorPos = backup_pos;
|
||||
|
||||
// We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug.
|
||||
// FIXME-NAV: Pressing NavActivate will trigger general child activation right before triggering our own below. Harmless but bizarre.
|
||||
PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
|
||||
PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
|
||||
PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
|
||||
@@ -4006,7 +4019,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!(flags & ImGuiInputTextFlags_MergedItem))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
||||
return false;
|
||||
item_status_flags = g.LastItemData.StatusFlags;
|
||||
}
|
||||
@@ -4017,21 +4030,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// We are only allowed to access the state if we are already the active widget.
|
||||
ImGuiInputTextState* state = GetInputTextState(id);
|
||||
|
||||
const bool focus_requested_by_code = (item_status_flags & ImGuiItemStatusFlags_FocusedByCode) != 0;
|
||||
const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
|
||||
|
||||
const bool user_clicked = hovered && io.MouseClicked[0];
|
||||
const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
|
||||
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
|
||||
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
|
||||
|
||||
bool clear_active_id = false;
|
||||
bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline);
|
||||
bool select_all = false;
|
||||
|
||||
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
|
||||
|
||||
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
|
||||
const bool init_make_active = (user_clicked || user_scroll_finish || user_nav_input_start || focus_requested_by_code || focus_requested_by_tabbing);
|
||||
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
|
||||
const bool init_state = (init_make_active || user_scroll_active);
|
||||
if ((init_state && g.ActiveId != id) || init_changed_specs)
|
||||
{
|
||||
@@ -4067,13 +4078,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->ID = id;
|
||||
state->ScrollX = 0.0f;
|
||||
stb_textedit_initialize_state(&state->Stb, !is_multiline);
|
||||
if (!is_multiline && focus_requested_by_code)
|
||||
}
|
||||
|
||||
if (!is_multiline)
|
||||
{
|
||||
if (flags & ImGuiInputTextFlags_AutoSelectAll)
|
||||
select_all = true;
|
||||
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
|
||||
select_all = true;
|
||||
if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl))
|
||||
select_all = true;
|
||||
}
|
||||
|
||||
if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
|
||||
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
|
||||
if (!is_multiline && (focus_requested_by_tabbing || (user_clicked && io.KeyCtrl)))
|
||||
select_all = true;
|
||||
}
|
||||
|
||||
if (g.ActiveId != id && init_make_active)
|
||||
@@ -4106,7 +4124,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// Lock the decision of whether we are going to take the path displaying the cursor or selection
|
||||
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
|
||||
bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
||||
bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
||||
bool value_changed = false;
|
||||
bool enter_pressed = false;
|
||||
|
||||
@@ -4207,7 +4225,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
|
||||
if (io.InputQueueCharacters.Size > 0)
|
||||
{
|
||||
if (!ignore_char_inputs && !is_readonly && !user_nav_input_start)
|
||||
if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
|
||||
for (int n = 0; n < io.InputQueueCharacters.Size; n++)
|
||||
{
|
||||
// Insert character if they pass filtering
|
||||
@@ -4248,6 +4266,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable);
|
||||
const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable;
|
||||
|
||||
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
|
||||
const bool is_validate_enter = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter);
|
||||
const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressedMap(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
|
||||
const bool is_cancel = IsKeyPressedMap(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed);
|
||||
|
||||
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
|
||||
@@ -4268,7 +4291,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
|
||||
}
|
||||
else if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter))
|
||||
else if (is_validate_enter)
|
||||
{
|
||||
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
||||
if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
|
||||
@@ -4282,7 +4305,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->OnKeyPressed((int)c);
|
||||
}
|
||||
}
|
||||
else if (IsKeyPressedMap(ImGuiKey_Escape))
|
||||
else if (is_validate_nav)
|
||||
{
|
||||
IM_ASSERT(!is_validate_enter);
|
||||
enter_pressed = clear_active_id = true;
|
||||
}
|
||||
else if (is_cancel)
|
||||
{
|
||||
clear_active_id = cancel_edit = true;
|
||||
}
|
||||
@@ -4767,6 +4795,30 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag
|
||||
return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
|
||||
}
|
||||
|
||||
// ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation.
|
||||
// Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting.
|
||||
static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V)
|
||||
{
|
||||
// This check is optional. Suppose we have two color widgets side by side, both widgets display different colors, but both colors have hue and/or saturation undefined.
|
||||
// With color check: hue/saturation is preserved in one widget. Editing color in one widget would reset hue/saturation in another one.
|
||||
// Without color check: common hue/saturation would be displayed in all widgets that have hue/saturation undefined.
|
||||
// g.ColorEditLastColor is stored as ImU32 RGB value: this essentially gives us color equality check with reduced precision.
|
||||
// Tiny external color changes would not be detected and this check would still pass. This is OK, since we only restore hue/saturation _only_ if they are undefined,
|
||||
// therefore this change flipping hue/saturation from undefined to a very tiny value would still be represented in color picker.
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
|
||||
return;
|
||||
|
||||
// When S == 0, H is undefined.
|
||||
// When H == 1 it wraps around to 0.
|
||||
if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1))
|
||||
*H = g.ColorEditLastHue;
|
||||
|
||||
// When V == 0, S is undefined.
|
||||
if (*V == 0.0f)
|
||||
*S = g.ColorEditLastSat;
|
||||
}
|
||||
|
||||
// Edit colors components (each component in 0.0f..1.0f range).
|
||||
// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
|
||||
// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.
|
||||
@@ -4822,13 +4874,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
{
|
||||
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
|
||||
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
|
||||
{
|
||||
if (f[1] == 0)
|
||||
f[0] = g.ColorEditLastHue;
|
||||
if (f[2] == 0)
|
||||
f[1] = g.ColorEditLastSat;
|
||||
}
|
||||
ColorEditRestoreHS(col, &f[0], &f[1], &f[2]);
|
||||
}
|
||||
int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) };
|
||||
|
||||
@@ -4963,7 +5009,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
g.ColorEditLastHue = f[0];
|
||||
g.ColorEditLastSat = f[1];
|
||||
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
memcpy(g.ColorEditLastColor, f, sizeof(float) * 3);
|
||||
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0));
|
||||
}
|
||||
if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV))
|
||||
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
@@ -5098,13 +5144,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
{
|
||||
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
|
||||
ColorConvertRGBtoHSV(R, G, B, H, S, V);
|
||||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
|
||||
{
|
||||
if (S == 0)
|
||||
H = g.ColorEditLastHue;
|
||||
if (V == 0)
|
||||
S = g.ColorEditLastSat;
|
||||
}
|
||||
ColorEditRestoreHS(col, &H, &S, &V);
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
@@ -5157,6 +5197,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
{
|
||||
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
|
||||
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
|
||||
|
||||
// Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square.
|
||||
if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
|
||||
H = g.ColorEditLastHue;
|
||||
value_changed = value_changed_sv = true;
|
||||
}
|
||||
if (!(flags & ImGuiColorEditFlags_NoOptions))
|
||||
@@ -5230,10 +5274,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
{
|
||||
if (flags & ImGuiColorEditFlags_InputRGB)
|
||||
{
|
||||
ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10 * 1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
|
||||
ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]);
|
||||
g.ColorEditLastHue = H;
|
||||
g.ColorEditLastSat = S;
|
||||
memcpy(g.ColorEditLastColor, col, sizeof(float) * 3);
|
||||
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0));
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
@@ -5287,13 +5331,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
G = col[1];
|
||||
B = col[2];
|
||||
ColorConvertRGBtoHSV(R, G, B, H, S, V);
|
||||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately.
|
||||
{
|
||||
if (S == 0)
|
||||
H = g.ColorEditLastHue;
|
||||
if (V == 0)
|
||||
S = g.ColorEditLastSat;
|
||||
}
|
||||
ColorEditRestoreHS(col, &H, &S, &V); // Fix local Hue as display below will use it immediately.
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
@@ -5900,12 +5938,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
toggled = true;
|
||||
}
|
||||
|
||||
if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open)
|
||||
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open)
|
||||
{
|
||||
toggled = true;
|
||||
NavMoveRequestCancel();
|
||||
}
|
||||
if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
|
||||
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
|
||||
{
|
||||
toggled = true;
|
||||
NavMoveRequestCancel();
|
||||
@@ -5976,7 +6014,7 @@ void ImGui::TreePush(const char* str_id)
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
Indent();
|
||||
window->DC.TreeDepth++;
|
||||
PushID(str_id ? str_id : "#TreePush");
|
||||
PushID(str_id);
|
||||
}
|
||||
|
||||
void ImGui::TreePush(const void* ptr_id)
|
||||
@@ -5984,7 +6022,7 @@ void ImGui::TreePush(const void* ptr_id)
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
Indent();
|
||||
window->DC.TreeDepth++;
|
||||
PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
|
||||
PushID(ptr_id);
|
||||
}
|
||||
|
||||
void ImGui::TreePushOverrideID(ImGuiID id)
|
||||
@@ -5993,7 +6031,7 @@ void ImGui::TreePushOverrideID(ImGuiID id)
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
Indent();
|
||||
window->DC.TreeDepth++;
|
||||
window->IDStack.push_back(id);
|
||||
PushOverrideID(id);
|
||||
}
|
||||
|
||||
void ImGui::TreePop()
|
||||
@@ -6147,20 +6185,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
|
||||
}
|
||||
|
||||
bool item_add;
|
||||
const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;
|
||||
if (disabled_item)
|
||||
{
|
||||
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
|
||||
item_add = ItemAdd(bb, id);
|
||||
g.CurrentItemFlags = backup_item_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
item_add = ItemAdd(bb, id);
|
||||
}
|
||||
|
||||
const bool item_add = ItemAdd(bb, id, NULL, disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None);
|
||||
if (span_all_columns)
|
||||
{
|
||||
window->ClipRect.Min.x = backup_clip_rect_min_x;
|
||||
@@ -6172,7 +6198,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
|
||||
if (disabled_item && !disabled_global) // Only testing this as an optimization
|
||||
BeginDisabled(true);
|
||||
BeginDisabled();
|
||||
|
||||
// FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only,
|
||||
// which would be advantageous since most selectable are not selected.
|
||||
@@ -6209,7 +6235,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
{
|
||||
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
|
||||
{
|
||||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos));
|
||||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); // (bb == NavRect)
|
||||
g.NavDisableHighlight = true;
|
||||
}
|
||||
}
|
||||
@@ -6474,7 +6500,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
float v0 = values_getter(data, (0 + values_offset) % values_count);
|
||||
float t0 = 0.0f;
|
||||
ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
|
||||
float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
|
||||
float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
|
||||
|
||||
const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
|
||||
const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
|
||||
@@ -6690,21 +6716,21 @@ void ImGui::EndMenuBar()
|
||||
// Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
|
||||
if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
||||
{
|
||||
// Try to find out if the request is for one of our child menu
|
||||
ImGuiWindow* nav_earliest_child = g.NavWindow;
|
||||
while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
|
||||
nav_earliest_child = nav_earliest_child->ParentWindow;
|
||||
if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None)
|
||||
if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
|
||||
{
|
||||
// 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)
|
||||
// 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 bothering)
|
||||
const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
|
||||
IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check
|
||||
FocusWindow(window);
|
||||
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
|
||||
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
|
||||
g.NavDisableMouseHover = g.NavMousePosDirty = true;
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
||||
NavMoveRequestCancel();
|
||||
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6797,7 +6823,7 @@ void ImGui::EndMainMenuBar()
|
||||
End();
|
||||
}
|
||||
|
||||
bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
@@ -6860,17 +6886,19 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Menu inside a menu
|
||||
// Menu inside a regular/vertical menu
|
||||
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
|
||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
|
||||
popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
|
||||
float icon_w = 0.0f; // FIXME: This not currently exposed for BeginMenu() however you can call window->DC.MenuColumns.DeclColumns(w, 0, 0, 0) yourself
|
||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
||||
RenderText(text_pos, label);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
||||
RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
|
||||
}
|
||||
if (!enabled)
|
||||
@@ -6887,38 +6915,30 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
// Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu
|
||||
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
|
||||
bool moving_toward_other_child_menu = false;
|
||||
|
||||
ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
|
||||
if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
|
||||
{
|
||||
// FIXME-DPI: Values should be derived from a master "scale" factor.
|
||||
float ref_unit = g.FontSize; // FIXME-DPI
|
||||
ImRect next_window_rect = child_menu_window->Rect();
|
||||
ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
|
||||
ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
|
||||
ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
|
||||
ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
|
||||
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.
|
||||
ta.x += (window->Pos.x < child_menu_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 // FIXME: Multiply by fb_scale?
|
||||
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
|
||||
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // add a bit of extra slack.
|
||||
ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues (FIXME: ??)
|
||||
tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
|
||||
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f);
|
||||
moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
|
||||
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
|
||||
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_other_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
|
||||
}
|
||||
|
||||
// FIXME: Hovering a disabled BeginMenu or MenuItem won't close us
|
||||
if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu)
|
||||
want_close = true;
|
||||
|
||||
if (!menu_is_open && hovered && pressed) // Click to open
|
||||
// Open
|
||||
if (!menu_is_open && pressed) // Click/activate to open
|
||||
want_open = true;
|
||||
else if (!menu_is_open && hovered && !moving_toward_other_child_menu) // Hover to open
|
||||
want_open = true;
|
||||
|
||||
if (g.NavActivateId == id)
|
||||
{
|
||||
want_close = menu_is_open;
|
||||
want_open = !menu_is_open;
|
||||
}
|
||||
if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
|
||||
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
|
||||
{
|
||||
want_open = true;
|
||||
NavMoveRequestCancel();
|
||||
@@ -6936,7 +6956,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
{
|
||||
want_open = true;
|
||||
}
|
||||
else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
|
||||
else if (g.NavId == id && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
|
||||
{
|
||||
want_open = true;
|
||||
NavMoveRequestCancel();
|
||||
@@ -6975,6 +6995,11 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
return menu_is_open;
|
||||
}
|
||||
|
||||
bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
{
|
||||
return BeginMenuEx(label, NULL, enabled);
|
||||
}
|
||||
|
||||
void ImGui::EndMenu()
|
||||
{
|
||||
// Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
|
||||
@@ -6982,11 +7007,12 @@ void ImGui::EndMenu()
|
||||
// However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
|
||||
{
|
||||
ClosePopupToLevel(g.BeginPopupStack.Size, true);
|
||||
NavMoveRequestCancel();
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
|
||||
if (g.NavWindow && (g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow == window)
|
||||
{
|
||||
ClosePopupToLevel(g.BeginPopupStack.Size, true);
|
||||
NavMoveRequestCancel();
|
||||
}
|
||||
|
||||
EndPopup();
|
||||
}
|
||||
@@ -7007,7 +7033,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
bool pressed;
|
||||
PushID(label);
|
||||
if (!enabled)
|
||||
BeginDisabled(true);
|
||||
BeginDisabled();
|
||||
const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
@@ -7016,10 +7042,11 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
|
||||
float w = label_size.x;
|
||||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
|
||||
pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
|
||||
PopStyleVar();
|
||||
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
||||
RenderText(text_pos, label);
|
||||
window->DC.CursorPos.x += IM_FLOOR(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().
|
||||
}
|
||||
else
|
||||
@@ -7914,9 +7941,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
if (p_open && !*p_open)
|
||||
{
|
||||
PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);
|
||||
ItemAdd(ImRect(), id);
|
||||
PopItemFlag();
|
||||
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7994,9 +8019,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'.
|
||||
if (tab_appearing && (!tab_bar_appearing || tab_is_new))
|
||||
{
|
||||
PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);
|
||||
ItemAdd(ImRect(), id);
|
||||
PopItemFlag();
|
||||
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
|
||||
if (is_tab_button)
|
||||
return false;
|
||||
return tab_contents_visible;
|
||||
@@ -8153,6 +8176,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
TabBarCloseTab(tab_bar, tab);
|
||||
}
|
||||
|
||||
// Forward Hovered state so IsItemHovered() after Begin() can work (even though we are technically hovering our parent)
|
||||
// That state is copied to window->DockTabItemStatusFlags by our caller.
|
||||
if (docked_window && (hovered || g.HoveredId == close_button_id))
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
|
||||
|
||||
// Restore main window position so user can draw there
|
||||
if (want_clip_rect)
|
||||
PopClipRect();
|
||||
|
||||
Reference in New Issue
Block a user