mirror of
https://github.com/wolfpld/tracy.git
synced 2025-03-20 07:40:02 +08:00
Update ImGui to 1.73.
This commit is contained in:
+179
-108
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.72b
|
||||
// dear imgui, v1.73
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -399,37 +399,37 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||
// See the series of events below and the corresponding state reported by dear imgui:
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
|
||||
// Frame N+0 (mouse is outside bb) - - - - - -
|
||||
// Frame N+1 (mouse moves inside bb) - true - - - -
|
||||
// Frame N+0 (mouse is outside bb) - - - - - -
|
||||
// Frame N+1 (mouse moves inside bb) - true - - - -
|
||||
// Frame N+2 (mouse button is down) - true true true - true
|
||||
// Frame N+3 (mouse button is down) - true true - - -
|
||||
// Frame N+3 (mouse button is down) - true true - - -
|
||||
// Frame N+4 (mouse moves outside bb) - - true - - -
|
||||
// Frame N+5 (mouse moves inside bb) - true true - - -
|
||||
// Frame N+6 (mouse button is released) true true - - true -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
// Frame N+8 (mouse moves outside bb) - - - - - -
|
||||
// Frame N+6 (mouse button is released) true true - - true -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
// Frame N+8 (mouse moves outside bb) - - - - - -
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
|
||||
// Frame N+2 (mouse button is down) true true true true - true
|
||||
// Frame N+3 (mouse button is down) - true true - - -
|
||||
// Frame N+6 (mouse button is released) - true - - true -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
// Frame N+3 (mouse button is down) - true true - - -
|
||||
// Frame N+6 (mouse button is released) - true - - true -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
|
||||
// Frame N+2 (mouse button is down) - true - - - true
|
||||
// Frame N+3 (mouse button is down) - true - - - -
|
||||
// Frame N+3 (mouse button is down) - true - - - -
|
||||
// Frame N+6 (mouse button is released) true true - - - -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
|
||||
// Frame N+0 (mouse button is down) - true - - - true
|
||||
// Frame N+1 (mouse button is down) - true - - - -
|
||||
// Frame N+1 (mouse button is down) - true - - - -
|
||||
// Frame N+2 (mouse button is released) - true - - - -
|
||||
// Frame N+3 (mouse button is released) - true - - - -
|
||||
// Frame N+3 (mouse button is released) - true - - - -
|
||||
// Frame N+4 (mouse button is down) true true true true - true
|
||||
// Frame N+5 (mouse button is down) - true true - - -
|
||||
// Frame N+5 (mouse button is down) - true true - - -
|
||||
// Frame N+6 (mouse button is released) - true - - true -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
// Frame N+7 (mouse button is released) - true - - - -
|
||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Note that some combinations are supported,
|
||||
// - PressedOnDragDropHold can generally be associated with any flag.
|
||||
@@ -439,7 +439,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||
// Repeat+ Repeat+ Repeat+ Repeat+
|
||||
// PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Frame N+0 (mouse button is down) - true - true
|
||||
// Frame N+0 (mouse button is down) - true - true
|
||||
// ... - - - -
|
||||
// Frame N + RepeatDelay true true - true
|
||||
// ... - - - -
|
||||
@@ -1261,7 +1261,10 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
|
||||
if (!ItemAdd(bb, 0))
|
||||
{
|
||||
if (columns)
|
||||
{
|
||||
PopColumnsBackground();
|
||||
columns->LineMinY = window->DC.CursorPos.y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1361,19 +1364,37 @@ static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs)
|
||||
// Shrink excess width from a set of item, by removing width from the larger items first.
|
||||
void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess)
|
||||
{
|
||||
if (count > 1)
|
||||
ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
|
||||
if (count == 1)
|
||||
{
|
||||
items[0].Width = ImMax(items[0].Width - width_excess, 1.0f);
|
||||
return;
|
||||
}
|
||||
ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
|
||||
int count_same_width = 1;
|
||||
while (width_excess > 0.0f && count_same_width < count)
|
||||
{
|
||||
while (count_same_width < count && items[0].Width == items[count_same_width].Width)
|
||||
while (count_same_width < count && items[0].Width <= items[count_same_width].Width)
|
||||
count_same_width++;
|
||||
float width_to_remove_per_item_max = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
|
||||
float width_to_remove_per_item = ImMin(width_excess / count_same_width, width_to_remove_per_item_max);
|
||||
float max_width_to_remove_per_item = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
|
||||
float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item);
|
||||
for (int item_n = 0; item_n < count_same_width; item_n++)
|
||||
items[item_n].Width -= width_to_remove_per_item;
|
||||
width_excess -= width_to_remove_per_item * count_same_width;
|
||||
}
|
||||
|
||||
// Round width and redistribute remainder left-to-right (could make it an option of the function?)
|
||||
// Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator.
|
||||
width_excess = 0.0f;
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
float width_rounded = ImFloor(items[n].Width);
|
||||
width_excess += items[n].Width - width_rounded;
|
||||
items[n].Width = width_rounded;
|
||||
}
|
||||
if (width_excess > 0.0f)
|
||||
for (int n = 0; n < count; n++)
|
||||
if (items[n].Index < (int)(width_excess + 0.01f))
|
||||
items[n].Width += 1.0f;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -1898,11 +1919,14 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiAxis axis = (flags & ImGuiDragFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||
const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
const bool has_min_max = (v_min != v_max);
|
||||
const bool is_power = (power != 1.0f && is_decimal && has_min_max && (v_max - v_min < FLT_MAX));
|
||||
const bool is_clamped = (v_min < v_max);
|
||||
const bool is_power = (power != 1.0f && is_decimal && is_clamped && (v_max - v_min < FLT_MAX));
|
||||
const bool is_locked = (v_min > v_max);
|
||||
if (is_locked)
|
||||
return false;
|
||||
|
||||
// Default tweak speed
|
||||
if (v_speed == 0.0f && has_min_max && (v_max - v_min < FLT_MAX))
|
||||
if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
|
||||
v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
|
||||
|
||||
// Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
|
||||
@@ -1930,7 +1954,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
// Clear current value on activation
|
||||
// Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300.
|
||||
bool is_just_activated = g.ActiveIdIsJustActivated;
|
||||
bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
|
||||
bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
|
||||
bool is_drag_direction_change_with_power = is_power && ((adjust_delta < 0 && g.DragCurrentAccum > 0) || (adjust_delta > 0 && g.DragCurrentAccum < 0));
|
||||
if (is_just_activated || is_already_past_limits_and_pushing_outward || is_drag_direction_change_with_power)
|
||||
{
|
||||
@@ -1954,12 +1978,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
// Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range
|
||||
FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
|
||||
FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min));
|
||||
v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min);
|
||||
v_cur = v_min + (SIGNEDTYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min);
|
||||
v_old_ref_for_accum_remainder = v_old_norm_curved;
|
||||
}
|
||||
else
|
||||
{
|
||||
v_cur += (TYPE)g.DragCurrentAccum;
|
||||
v_cur += (SIGNEDTYPE)g.DragCurrentAccum;
|
||||
}
|
||||
|
||||
// Round to user desired precision based on format string
|
||||
@@ -1982,7 +2006,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
v_cur = (TYPE)0;
|
||||
|
||||
// Clamp values (+ handle overflow/wrap-around for integer types)
|
||||
if (*v != v_cur && has_min_max)
|
||||
if (*v != v_cur && is_clamped)
|
||||
{
|
||||
if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
|
||||
v_cur = v_min;
|
||||
@@ -2460,13 +2484,13 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
|
||||
IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2);
|
||||
return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb);
|
||||
case ImGuiDataType_U32:
|
||||
IM_ASSERT(*(const ImU32*)v_min <= IM_U32_MAX/2);
|
||||
IM_ASSERT(*(const ImU32*)v_max <= IM_U32_MAX/2);
|
||||
return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb);
|
||||
case ImGuiDataType_S64:
|
||||
IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2);
|
||||
return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb);
|
||||
case ImGuiDataType_U64:
|
||||
IM_ASSERT(*(const ImU64*)v_min <= IM_U64_MAX/2);
|
||||
IM_ASSERT(*(const ImU64*)v_max <= IM_U64_MAX/2);
|
||||
return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb);
|
||||
case ImGuiDataType_Float:
|
||||
IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f);
|
||||
@@ -3198,21 +3222,21 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im
|
||||
}
|
||||
|
||||
// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
|
||||
#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left
|
||||
#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right
|
||||
#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up
|
||||
#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down
|
||||
#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line
|
||||
#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line
|
||||
#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text
|
||||
#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text
|
||||
#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor
|
||||
#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor
|
||||
#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo
|
||||
#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo
|
||||
#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word
|
||||
#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word
|
||||
#define STB_TEXTEDIT_K_SHIFT 0x20000
|
||||
#define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left
|
||||
#define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right
|
||||
#define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up
|
||||
#define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down
|
||||
#define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line
|
||||
#define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line
|
||||
#define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text
|
||||
#define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text
|
||||
#define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor
|
||||
#define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor
|
||||
#define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo
|
||||
#define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo
|
||||
#define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word
|
||||
#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
|
||||
#define STB_TEXTEDIT_K_SHIFT 0x400000
|
||||
|
||||
#define STB_TEXTEDIT_IMPLEMENTATION
|
||||
#include "imstb_textedit.h"
|
||||
@@ -3380,7 +3404,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
BeginGroup();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
|
||||
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
|
||||
|
||||
@@ -4176,7 +4200,12 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB))
|
||||
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV))
|
||||
{
|
||||
// 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 (f[1] == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
|
||||
f[0] = g.ColorEditLastHue;
|
||||
}
|
||||
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]) };
|
||||
|
||||
bool value_changed = false;
|
||||
@@ -4213,14 +4242,17 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
if (n > 0)
|
||||
SameLine(0, style.ItemInnerSpacing.x);
|
||||
SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last);
|
||||
|
||||
// Disable Hue edit when Saturation is zero
|
||||
const bool disable_hue_edit = (n == 0 && (flags & ImGuiColorEditFlags_DisplayHSV) && i[1] == 0);
|
||||
if (flags & ImGuiColorEditFlags_Float)
|
||||
{
|
||||
value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
|
||||
value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, disable_hue_edit ? +FLT_MAX : 0.0f, disable_hue_edit ? -FLT_MAX : hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
|
||||
value_changed_as_float |= value_changed;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
|
||||
value_changed |= DragInt(ids[n], &i[n], 1.0f, disable_hue_edit ? INT_MAX : 0, disable_hue_edit ? INT_MIN : hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
|
||||
}
|
||||
if (!(flags & ImGuiColorEditFlags_NoOptions))
|
||||
OpenPopupOnItemClick("context");
|
||||
@@ -4300,7 +4332,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
for (int n = 0; n < 4; n++)
|
||||
f[n] = i[n] / 255.0f;
|
||||
if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB))
|
||||
{
|
||||
g.ColorEditLastHue = f[0];
|
||||
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
memcpy(g.ColorEditLastColor, f, sizeof(float) * 3);
|
||||
}
|
||||
if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV))
|
||||
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
|
||||
|
||||
@@ -4402,17 +4438,19 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU
|
||||
}
|
||||
|
||||
// Helper for ColorPicker4()
|
||||
static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)
|
||||
static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
|
||||
{
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK);
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE);
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK);
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE);
|
||||
ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha);
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8));
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8));
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8));
|
||||
ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8));
|
||||
}
|
||||
|
||||
// Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
|
||||
// (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.)
|
||||
// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
|
||||
// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0)
|
||||
bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -4475,9 +4513,16 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
float H = col[0], S = col[1], V = col[2];
|
||||
float R = col[0], G = col[1], B = col[2];
|
||||
if (flags & ImGuiColorEditFlags_InputRGB)
|
||||
{
|
||||
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
|
||||
ColorConvertRGBtoHSV(R, G, B, H, S, V);
|
||||
if (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
|
||||
H = g.ColorEditLastHue;
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
ColorConvertHSVtoRGB(H, S, V, R, G, B);
|
||||
}
|
||||
|
||||
bool value_changed = false, value_changed_h = false, value_changed_sv = false;
|
||||
|
||||
@@ -4599,6 +4644,8 @@ 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]);
|
||||
g.ColorEditLastHue = H;
|
||||
memcpy(g.ColorEditLastColor, col, sizeof(float) * 3);
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
@@ -4652,6 +4699,8 @@ 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 (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately.
|
||||
H = g.ColorEditLastHue;
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
{
|
||||
@@ -4662,17 +4711,22 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
}
|
||||
}
|
||||
|
||||
ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
|
||||
ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
|
||||
ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, 1.0f));
|
||||
const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha);
|
||||
const ImU32 col_black = IM_COL32(0,0,0,style_alpha8);
|
||||
const ImU32 col_white = IM_COL32(255,255,255,style_alpha8);
|
||||
const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8);
|
||||
const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) };
|
||||
|
||||
ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
|
||||
ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
|
||||
ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!!
|
||||
|
||||
const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) };
|
||||
ImVec2 sv_cursor_pos;
|
||||
|
||||
if (flags & ImGuiColorEditFlags_PickerHueWheel)
|
||||
{
|
||||
// Render Hue Wheel
|
||||
const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
|
||||
const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
|
||||
const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
|
||||
for (int n = 0; n < 6; n++)
|
||||
{
|
||||
@@ -4680,13 +4734,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
|
||||
const int vert_start_idx = draw_list->VtxBuffer.Size;
|
||||
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
|
||||
draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);
|
||||
draw_list->PathStroke(col_white, false, wheel_thickness);
|
||||
const int vert_end_idx = draw_list->VtxBuffer.Size;
|
||||
|
||||
// Paint colors over existing vertices
|
||||
ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
|
||||
ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
|
||||
ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);
|
||||
ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]);
|
||||
}
|
||||
|
||||
// Render Cursor + preview on Hue Wheel
|
||||
@@ -4696,8 +4750,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
|
||||
int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
|
||||
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
|
||||
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments);
|
||||
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);
|
||||
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments);
|
||||
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
|
||||
|
||||
// Render SV triangle (rotated according to hue)
|
||||
ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
|
||||
@@ -4707,46 +4761,46 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
draw_list->PrimReserve(6, 6);
|
||||
draw_list->PrimVtx(tra, uv_white, hue_color32);
|
||||
draw_list->PrimVtx(trb, uv_white, hue_color32);
|
||||
draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
|
||||
draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
|
||||
draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
|
||||
draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
|
||||
draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
|
||||
draw_list->PrimVtx(trc, uv_white, col_white);
|
||||
draw_list->PrimVtx(tra, uv_white, 0);
|
||||
draw_list->PrimVtx(trb, uv_white, col_white);
|
||||
draw_list->PrimVtx(trc, uv_white, 0);
|
||||
draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
|
||||
sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
|
||||
}
|
||||
else if (flags & ImGuiColorEditFlags_PickerHueBar)
|
||||
{
|
||||
// Render SV Square
|
||||
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
|
||||
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
|
||||
RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);
|
||||
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
|
||||
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
|
||||
RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
|
||||
sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
|
||||
sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
|
||||
|
||||
// Render Hue Bar
|
||||
for (int i = 0; i < 6; ++i)
|
||||
draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);
|
||||
draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
|
||||
float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);
|
||||
RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
|
||||
RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
|
||||
RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
|
||||
}
|
||||
|
||||
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
|
||||
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
|
||||
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);
|
||||
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12);
|
||||
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);
|
||||
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
|
||||
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12);
|
||||
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
|
||||
|
||||
// Render alpha bar
|
||||
if (alpha_bar)
|
||||
{
|
||||
float alpha = ImSaturate(col[3]);
|
||||
ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
|
||||
RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
|
||||
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK);
|
||||
RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
|
||||
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
|
||||
float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
|
||||
RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
|
||||
RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
|
||||
RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
@@ -5143,31 +5197,38 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
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(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
|
||||
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
|
||||
ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->WorkRect.Max.x, window->DC.CursorPos.y + frame_height));
|
||||
ImRect frame_bb;
|
||||
frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
|
||||
frame_bb.Min.y = window->DC.CursorPos.y;
|
||||
frame_bb.Max.x = window->WorkRect.Max.x;
|
||||
frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
|
||||
if (display_frame)
|
||||
{
|
||||
// Framed header expand a little outside the default padding
|
||||
// Framed header expand a little outside the default padding, to the edge of InnerClipRect
|
||||
// (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
|
||||
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f);
|
||||
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f);
|
||||
}
|
||||
|
||||
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);
|
||||
const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
|
||||
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
|
||||
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
|
||||
ItemSize(ImVec2(text_width, frame_height), text_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 if we want the hit test to be done up to the right side of the content or not)
|
||||
const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y);
|
||||
bool is_open = TreeNodeBehaviorIsOpen(id, flags);
|
||||
bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||
|
||||
ImRect interact_bb = frame_bb;
|
||||
if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0)
|
||||
interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f;
|
||||
|
||||
// Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
|
||||
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
||||
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
|
||||
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||
bool is_open = TreeNodeBehaviorIsOpen(id, flags);
|
||||
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
|
||||
window->DC.TreeMayJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
|
||||
|
||||
bool item_add = ItemAdd(interact_bb, id);
|
||||
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
||||
@@ -5239,7 +5300,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
|
||||
// Render
|
||||
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
||||
const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y);
|
||||
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
|
||||
if (display_frame)
|
||||
{
|
||||
@@ -5247,7 +5307,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||
RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
|
||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||
else if (!is_leaf)
|
||||
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
|
||||
else // Leaf without bullet, left-adjusted text
|
||||
text_pos.x -= text_offset_x;
|
||||
if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
||||
frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
||||
if (g.LogEnabled)
|
||||
@@ -5273,11 +5338,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||
}
|
||||
|
||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||
RenderBullet(window->DrawList, frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y), text_col);
|
||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||
else if (!is_leaf)
|
||||
RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
|
||||
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&text_pos, ">");
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
@@ -5320,13 +5384,16 @@ void ImGui::TreePop()
|
||||
Unindent();
|
||||
|
||||
window->DC.TreeDepth--;
|
||||
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
||||
|
||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
|
||||
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
if (g.NavIdIsAlive && (window->DC.TreeStoreMayJumpToParentOnPop & (1 << window->DC.TreeDepth)))
|
||||
if (g.NavIdIsAlive && (window->DC.TreeMayJumpToParentOnPopMask & tree_depth_mask))
|
||||
{
|
||||
SetNavID(window->IDStack.back(), g.NavLayer);
|
||||
NavMoveRequestCancel();
|
||||
}
|
||||
window->DC.TreeStoreMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1;
|
||||
window->DC.TreeMayJumpToParentOnPopMask &= tree_depth_mask - 1;
|
||||
|
||||
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
||||
PopID();
|
||||
@@ -5473,7 +5540,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
||||
|
||||
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
|
||||
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
|
||||
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
|
||||
{
|
||||
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
|
||||
@@ -5593,7 +5660,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item
|
||||
// We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().
|
||||
ImVec2 size;
|
||||
size.x = 0.0f;
|
||||
size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f;
|
||||
size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f);
|
||||
return ListBoxHeader(label, size);
|
||||
}
|
||||
|
||||
@@ -6265,8 +6332,8 @@ ImGuiTabBar::ImGuiTabBar()
|
||||
ID = 0;
|
||||
SelectedTabId = NextSelectedTabId = VisibleTabId = 0;
|
||||
CurrFrameVisible = PrevFrameVisible = -1;
|
||||
ContentsHeight = 0.0f;
|
||||
OffsetMax = OffsetNextTab = 0.0f;
|
||||
LastTabContentHeight = 0.0f;
|
||||
OffsetMax = OffsetMaxIdeal = OffsetNextTab = 0.0f;
|
||||
ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f;
|
||||
Flags = ImGuiTabBarFlags_None;
|
||||
ReorderRequestTabId = 0;
|
||||
@@ -6348,7 +6415,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
||||
tab_bar->FramePadding = g.Style.FramePadding;
|
||||
|
||||
// Layout
|
||||
ItemSize(ImVec2(0.0f /*tab_bar->OffsetMax*/, tab_bar->BarRect.GetHeight())); // Don't feed width back
|
||||
ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight()));
|
||||
window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
|
||||
|
||||
// Draw separator
|
||||
@@ -6381,9 +6448,9 @@ void ImGui::EndTabBar()
|
||||
// Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed().
|
||||
const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
|
||||
if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
|
||||
tab_bar->ContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f);
|
||||
tab_bar->LastTabContentHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f);
|
||||
else
|
||||
window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->ContentsHeight;
|
||||
window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->LastTabContentHeight;
|
||||
|
||||
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
||||
PopID();
|
||||
@@ -6502,11 +6569,13 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
{
|
||||
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
|
||||
tab->Width = ImMin(tab->WidthContents, tab_max_width);
|
||||
IM_ASSERT(tab->Width > 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Layout all active tabs
|
||||
float offset_x = initial_offset_x;
|
||||
float offset_x_ideal = offset_x;
|
||||
tab_bar->OffsetNextTab = offset_x; // This is used by non-reorderable tab bar where the submission order is always honored.
|
||||
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
|
||||
{
|
||||
@@ -6515,8 +6584,10 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID)
|
||||
scroll_track_selected_tab_id = tab->ID;
|
||||
offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
|
||||
offset_x_ideal += tab->WidthContents + g.Style.ItemInnerSpacing.x;
|
||||
}
|
||||
tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
tab_bar->OffsetMaxIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f);
|
||||
|
||||
// Horizontal scrolling buttons
|
||||
const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
|
||||
@@ -6631,7 +6702,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
||||
float tab_x1 = tab->Offset + (order > 0 ? -margin : 0.0f);
|
||||
float tab_x2 = tab->Offset + tab->Width + (order + 1 < tab_bar->Tabs.Size ? margin : 1.0f);
|
||||
tab_bar->ScrollingTargetDistToVisibility = 0.0f;
|
||||
if (tab_bar->ScrollingTarget > tab_x1)
|
||||
if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= tab_bar->BarRect.GetWidth()))
|
||||
{
|
||||
tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f);
|
||||
tab_bar->ScrollingTarget = tab_x1;
|
||||
@@ -6895,7 +6966,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
ImRect bb(pos, pos + size);
|
||||
|
||||
// We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
|
||||
bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x);
|
||||
bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x > tab_bar->BarRect.Max.x);
|
||||
if (want_clip_rect)
|
||||
PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true);
|
||||
|
||||
@@ -7254,7 +7325,7 @@ void ImGui::PushColumnsBackground()
|
||||
return;
|
||||
window->DrawList->ChannelsSetCurrent(0);
|
||||
int cmd_size = window->DrawList->CmdBuffer.Size;
|
||||
PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
|
||||
PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
|
||||
IM_UNUSED(cmd_size);
|
||||
IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user