ставь чайник, зажигай плиту
-
Автор темы
- #1
ImGui: v1.79
(Просто попросили, самый простой элемент, по-моему мнению)
Обращайте внимание на комментарий в начале
Source code:
(Просто попросили, самый простой элемент, по-моему мнению)
Обращайте внимание на комментарий в начале
Source code:
C++:
struct animation {
bool clicked;
bool reverse;
float size;
float mult;
};
C++:
// callback == v
// name == label
static std::map<ImGuiID, animation> circle_anim;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(name);
const ImVec2 label_size = CalcTextSize(name, NULL, true);
const float square_sz = GetFrameHeight();
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);
if (!ItemAdd(total_bb, id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
if (pressed)
{
*callback = !(*callback);
MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
float radius = square_sz * 0.82f;
auto it_circle = circle_anim.find(id);
if (it_circle == circle_anim.end())
{
circle_anim.insert({ id, {false, false, 0.f, 0.f} });
it_circle = circle_anim.find(id);
}
if (pressed && *callback)
it_circle->second.clicked = true;
else if (pressed && !(*callback) && it_circle->second.clicked)
{
it_circle->second.mult = 0.f;
it_circle->second.size = 0.f;
it_circle->second.reverse = false;
it_circle->second.clicked = false;
}
if (it_circle->second.clicked)
{
if (!it_circle->second.reverse)
{
it_circle->second.size = ImClamp(it_circle->second.size + 3.f * GetIO().DeltaTime, 0.f, 1.f);
it_circle->second.mult = ImClamp(it_circle->second.mult + 6.f * GetIO().DeltaTime, 0.f, 1.f);
if (it_circle->second.mult >= 0.99f)
it_circle->second.reverse = true;
}
else
{
it_circle->second.size = ImClamp(it_circle->second.size + 3.f * GetIO().DeltaTime, 0.f, 1.f);
it_circle->second.mult = ImClamp(it_circle->second.mult - 6.f * GetIO().DeltaTime, 0.f, 1.f);
if (it_circle->second.mult <= 0.01f)
{
it_circle->second.mult = 0.f;
it_circle->second.size = 0.f;
it_circle->second.reverse = false;
it_circle->second.clicked = false;
}
}
}
if (*callback)
{
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32(g_menu.menu_color.Value), true, style.FrameRounding);
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 5.f));
RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
}
ImU32 circle_col = GetColorU32(ImGuiCol_CheckMark, it_circle->second.mult * 0.7f);
if (it_circle->second.mult > 0.01f)
window->DrawList->AddCircleFilled(ImVec2(check_bb.Min.x + (check_bb.Max.x - check_bb.Min.x) / 2, check_bb.Min.y + (check_bb.Max.y - check_bb.Min.y) / 2), radius * it_circle->second.size, circle_col, 30);
// Better use clipped text (aligns and some else..)
if (label_size.x > 0.0f)
RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + ((check_bb.Max.y - check_bb.Min.y) / 2) - label_size.y / 2 - 1), name);
return pressed;