Исходник ImGui Button with animations

ставь чайник, зажигай плиту
Эксперт
Статус
Оффлайн
Регистрация
22 Май 2020
Сообщения
1,444
Реакции[?]
1,092
Поинты[?]
10K
ImGui: v1.79



Обращайте внимание на комментарий в начале

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;
 
Последнее редактирование:
Забаненный
Статус
Оффлайн
Регистрация
18 Июл 2020
Сообщения
902
Реакции[?]
200
Поинты[?]
1K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
error C2065: a_size: необъявленный идентификатор
 
Сверху Снизу