ставь чайник, зажигай плиту
-
Автор темы
- #1
ImGui: v1.79
Обращайте внимание на комментарий в начале
Source code:
Обращайте внимание на комментарий в начале
Source code:
C++:
struct button_animation {
bool clicked;
bool reverse;
float size;
float mult;
ImVec2 pos;
};
C++:
// name == label
static std::map<ImGuiID, button_animation> button_circle;
static std::map<ImGuiID, float> button_hover;
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);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(a_size, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, 0);
// Render
const ImU32 col = GetColorU32(ImGuiCol_Button);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
// Press button animation (Drawing circle in clipped area)
auto it_circle = button_circle.find(id);
if (it_circle == button_circle.end())
{
button_circle.insert({ id, {false, false, 0.f, 0.f, ImVec2(0, 0)} });
it_circle = button_circle.find(id);
}
// If pressed and wasn't active - start animation
if (pressed && !it_circle->second.clicked)
{
it_circle->second.clicked = true;
it_circle->second.pos = GetIO().MousePos;
}
// If pressed and was active - restart animation
else if (pressed && 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 = true;
it_circle->second.pos = GetIO().MousePos;
}
// If we have active animation - procedure it
if (it_circle->second.clicked)
{
// First stage - size(+) alpha(-)
if (!it_circle->second.reverse)
{
it_circle->second.size = ImClamp(it_circle->second.size + 1.5f * GetIO().DeltaTime, 0.f, 1.f);
it_circle->second.mult = ImClamp(it_circle->second.mult + 2.f * GetIO().DeltaTime, 0.f, 1.f);
// Go for the second stage
if (it_circle->second.mult >= 0.99f)
it_circle->second.reverse = true;
}
// Second stage - size(+) alpha(-)
else
{
it_circle->second.size = ImClamp(it_circle->second.size + 1.5f * GetIO().DeltaTime, 0.f, 1.f);
it_circle->second.mult = ImClamp(it_circle->second.mult - 2.f * GetIO().DeltaTime, 0.f, 1.f);
// Stop animation
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;
}
}
}
// Animated circle (on-press animation) color
ImVec4 circle_color = ImVec4(0.98f, 0.98f, 0.98f, it_circle->second.mult * 0.6f);
// Circle radius calcalution
float radius = ImMax(fabs(it_circle->second.pos.x - bb.Max.x), fabs(it_circle->second.pos.x - bb.Min.x)) * 2.f;
// Clip area to draw a cicrle inside frame
window->DrawList->PushClipRect(bb.Min, bb.Max);
window->DrawList->AddCircleFilled(it_circle->second.pos, radius * it_circle->second.size, GetColorU32(circle_color), 30);
window->DrawList->PopClipRect();
// hover animation
auto it_hover = button_hover.find(id);
if (it_hover == button_hover.end())
{
button_hover.insert({ id, {0.f} });
it_hover = button_hover.find(id);
}
it_hover->second = ImClamp(it_hover->second + 2.5f * GetIO().DeltaTime * (hovered ? 1.f : -1.f), 0.f, 1.f);
ImVec4 hovering_color = ImVec4(0.98f, 0.98f, 0.98f, it_hover->second * 0.4f);
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(hovering_color), GetStyle().FrameRounding);
ImGui::RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, name, NULL, &label_size, style.ButtonTextAlign, &bb);
return pressed;
Последнее редактирование: