mostly finished toggle + sliders

This commit is contained in:
yhqe committed 2026-03-27 00:30:28 -05:00
1 parent 6c17fd9b2f
commit 00a6b4d54e
2 files changed
+222 -30

No files matched your search

+99 -27
View File
@@ -1128,7 +1128,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float square_sz = GetFrameHeight();
const float square_sz = GetFrameHeight() - 2.5f;
const ImVec2 pos = window->DC.CursorPos;
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ItemSize(total_bb, style.FramePadding.y);
@@ -1146,27 +1146,34 @@ bool ImGui::Checkbox(const char* label, bool* v)
MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
const ImRect check_bb(pos + ImVec2(0.f, 2.5f), pos + ImVec2(square_sz, square_sz) + ImVec2(0.f, 2.5f));
RenderNavHighlight(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
RenderFrame(check_bb.Min, check_bb.Max, IM_COL32(55, 60, 75, 255), true, 5.f);
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value)
if (*v)
{
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
// This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox)
ImVec2 pad(ImMax(1.0f, IM_TRUNC(square_sz / 3.6f)), ImMax(1.0f, IM_TRUNC(square_sz / 3.6f)));
window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
}
else if (*v)
{
const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f));
RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
const ImU32 grad_tl = IM_COL32(133, 151, 255, 255);
const ImU32 grad_tr = IM_COL32(133, 151, 255, 255);
const ImU32 grad_br = IM_COL32(113, 131, 235, 255);
const ImU32 grad_bl = IM_COL32(113, 131, 235, 255);
window->DrawList->AddRectFilledMultiColor(check_bb.Min, check_bb.Max, grad_tl, grad_tr, grad_br, grad_bl);
for (int i = 0; i < 10; ++i)
{
const float t = (float)i / 9.0f;
const float r = 1.0f + t * 8.0f;
const float falloff = (1.0f - t) * (1.0f - t); // smoother fade
const int a = (int)(85.0f * falloff);
const float rounding = 5.0f + t * 3.0f;
window->DrawList->AddRect(check_bb.Min - ImVec2(r, r), check_bb.Max + ImVec2(r, r), IM_COL32(133, 151, 255, a), rounding, ImDrawFlags_None, 1.0f);
}
window->DrawList->AddRect(check_bb.Min - ImVec2(1.0f, 1.0f), check_bb.Max + ImVec2(1.0f, 1.0f), IM_COL32(133, 151, 255, 220), 5.0f, ImDrawFlags_None, 1.5f);
RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(3.0f, 3.0f), IM_COL32(255, 255, 255, 255), square_sz - 6.0f);
}
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
if (g.LogEnabled)
LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x + 5.f, check_bb.Min.y + style.FramePadding.y);
if (label_size.x > 0.0f)
RenderText(label_pos, label);
@@ -3061,8 +3068,17 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
const float w = CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
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));
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f) - ImVec2(0.f, 19.f));
const ImVec2 label_pos(frame_bb.Min.x, frame_bb.Min.y - label_size.y - style.ItemInnerSpacing.y);
ImVec2 total_min = frame_bb.Min;
ImVec2 total_max = frame_bb.Max;
if (label_size.x > 0.0f)
{
total_min.y = ImMin(total_min.y, label_pos.y);
total_max.x = ImMax(total_max.x, label_pos.x + label_size.x);
}
const ImRect total_bb(total_min, total_max);
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
ItemSize(total_bb, style.FramePadding.y);
@@ -3105,7 +3121,43 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
RenderFrame(frame_bb.Min, frame_bb.Max, IM_COL32(55, 60, 75, 255), true, style.FrameRounding);
// dude come on
double v_cur = 0.0, v_min_d = 0.0, v_max_d = 1.0;
switch (data_type)
{
case ImGuiDataType_S8: v_cur = (double)*(const ImS8*)p_data; v_min_d = (double)*(const ImS8*)p_min; v_max_d = (double)*(const ImS8*)p_max; break;
case ImGuiDataType_U8: v_cur = (double)*(const ImU8*)p_data; v_min_d = (double)*(const ImU8*)p_min; v_max_d = (double)*(const ImU8*)p_max; break;
case ImGuiDataType_S16: v_cur = (double)*(const ImS16*)p_data; v_min_d = (double)*(const ImS16*)p_min; v_max_d = (double)*(const ImS16*)p_max; break;
case ImGuiDataType_U16: v_cur = (double)*(const ImU16*)p_data; v_min_d = (double)*(const ImU16*)p_min; v_max_d = (double)*(const ImU16*)p_max; break;
case ImGuiDataType_S32: v_cur = (double)*(const ImS32*)p_data; v_min_d = (double)*(const ImS32*)p_min; v_max_d = (double)*(const ImS32*)p_max; break;
case ImGuiDataType_U32: v_cur = (double)*(const ImU32*)p_data; v_min_d = (double)*(const ImU32*)p_min; v_max_d = (double)*(const ImU32*)p_max; break;
case ImGuiDataType_S64: v_cur = (double)*(const ImS64*)p_data; v_min_d = (double)*(const ImS64*)p_min; v_max_d = (double)*(const ImS64*)p_max; break;
case ImGuiDataType_U64: v_cur = (double)*(const ImU64*)p_data; v_min_d = (double)*(const ImU64*)p_min; v_max_d = (double)*(const ImU64*)p_max; break;
case ImGuiDataType_Float: v_cur = (double)*(const float*)p_data; v_min_d = (double)*(const float*)p_min; v_max_d = (double)*(const float*)p_max; break;
case ImGuiDataType_Double: v_cur = *(const double*)p_data; v_min_d = *(const double*)p_min; v_max_d = *(const double*)p_max; break;
default: break;
}
float t = 0.0f;
if (v_max_d != v_min_d)
{
t = ImSaturate((float)((v_cur - v_min_d) / (v_max_d - v_min_d)));
t = ImFloor(t * 25.0f + 0.5f) / 25.0f;
}
const float fill_x = ImFloor(ImLerp(frame_bb.Min.x, frame_bb.Max.x, t) * 25.0f + 0.5f) / 25.0f;
if (fill_x > frame_bb.Min.x)
{
ImDrawList* draw_list = window->DrawList;
const ImVec2 fill_max(fill_x, frame_bb.Max.y);
const int vert_start_idx = draw_list->VtxBuffer.Size;
draw_list->AddRectFilled(frame_bb.Min, fill_max, IM_COL32(255, 255, 255, 255), 25.0f);
const int vert_end_idx = draw_list->VtxBuffer.Size;
ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, frame_bb.Min, fill_max, IM_COL32(129, 183, 255, 255), IM_COL32(137, 120, 255, 255));
}
// Slider behavior
ImRect grab_bb;
@@ -3113,19 +3165,39 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (value_changed)
MarkItemEdited(id);
// Render grab
if (grab_bb.Max.x > grab_bb.Min.x)
window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
// 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, p_data, format);
DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
if (g.LogEnabled)
LogSetNextTextDecoration("{", "}");
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
ImGuiStorage* storage = GetStateStorage();
const ImGuiID value_anim_id = id ^ 0x7A9C31F2;
float value_pop_t = storage->GetFloat(value_anim_id, 0.0f);
if (hovered)
value_pop_t = ImMin(value_pop_t + 6.0f * g.IO.DeltaTime, 1.0f);
else
value_pop_t = ImMax(value_pop_t - 8.0f * g.IO.DeltaTime, 0.0f);
storage->SetFloat(value_anim_id, value_pop_t);
if (value_pop_t > 0.0f)
{
const ImVec2 value_size = CalcTextSize(value_buf, NULL, true);
const float x = frame_bb.Max.x - value_size.x - style.FramePadding.x;
const float y_hidden = frame_bb.Max.y + style.FramePadding.y + value_size.y;
const float y_shown = frame_bb.Min.y - value_size.y - 3.5f;
const float pop = 1.0f - ImPow(1.0f - value_pop_t, 3.0f);
const ImVec2 value_pos(x, ImLerp(y_hidden, y_shown, pop));
// Clip so text inside the slider is masked, creating a "behind slider" effect.
window->DrawList->PushClipRect(window->ClipRect.Min, ImVec2(window->ClipRect.Max.x, frame_bb.Min.y), true);
RenderText(value_pos, value_buf);
window->DrawList->PopClipRect();
}
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
return value_changed;