• Я зарабатываю 100 000 RUB / месяц на этом сайте!

    А знаешь как? Я всего-лишь публикую (создаю темы), а админ мне платит. Трачу деньги на мороженое, робуксы и сервера в Minecraft. А ещё на паль из Китая. 

    Хочешь так же? Пиши и узнавай условия: https://t.me/alex_redact
    Реклама: https://t.me/yougame_official

Гайд Creating open and close animation for a BeginPopup in ImGui "1.91.9"

  • Автор темы Автор темы Remario
  • Дата начала Дата начала
get good, get zeus, for ever
Участник
Участник
Статус
Оффлайн
Регистрация
1 Июн 2018
Сообщения
704
Реакции
152



1. Добавить переменные в ImGuiContext

В файле imgui_internal.h внутри структуры ImGuiContext добавляем три новых булевых переменных :
Код:
Expand Collapse Copy
struct ImGuiContext

{

bool Skip_ClosePopupsCloseCurrentPopup;
bool Skip_ClosePopupsOverWindow;
bool Skip_ClosePopupsWhileNavUpdateCancelRequest;

};



2. Изменение в функции NavUpdate()
В файле imgui.cpp, находим функцию static void ImGui::NavUpdate().Внутри неё ищем вызов NavUpdateCancelRequest() и заменяем на :
if (g.Skip_ClosePopupsWhileNavUpdateCancelRequest == false)
NavUpdateCancelRequest();



3. Изменение в CloseCurrentPopup()
В том же файле imgui.cpp, находим функцию void ImGui::CloseCurrentPopup().Ищем строчку :

ClosePopupToLevel(popup_idx, true);
заменяем на :
if (g.Skip_ClosePopupsCloseCurrentPopup == false)
ClosePopupToLevel(popup_idx, true);



4. Изменение в ClosePopupsOverWindow()
В файле imgui.cpp, находим функцию :

void ImGui::ClosePopupsOverWindow(ImGuiWindow * ref_window, bool restore_focus_to_window_under_popup)

и добавляем проверку в самом начале :

if (g.Skip_ClosePopupsOverWindow)
return;





5. Структура с BeginPopup и анимациями
Код:
Expand Collapse Copy
#pragma once
#include <functional>

struct AnimatedPopup
{
    const char* label;
    bool open_next_frame = false;

    bool popup_open = false;
    bool popup_closing = false;
    bool force_close = false;

    float alpha = 0.0f;
    float slide_t = 0.0f;

    bool   anim_finished = false;
    bool   is_dragging = false;
    bool   user_moved = false;
    ImVec2 drag_offset = ImVec2(0, 0);

    ImVec2 base_pos = ImVec2(0, 0);
    ImVec2 current_pos = ImVec2(0, 0);
    ImVec2 closing_start = ImVec2(0, 0);

    float slide_distance = 25.0f;
    float alpha_speed = 12.0f;
    float slide_speed = 12.0f;
    ImVec2 padding = ImVec2(8, 4);

    AnimatedPopup(const char* popup_label, float a_speed, float s_speed, float slide_distance, ImVec2 popup_padding)
        : label(popup_label)
        , alpha_speed(a_speed)
        , slide_speed(s_speed)
        , slide_distance(slide_distance)
        , padding(popup_padding)
    {
    }

    void Open()
    {
        open_next_frame = true;
    }

    void Close()
    {
        if (popup_open && !popup_closing)
        {
            popup_closing = true;
            closing_start = anim_finished && user_moved ? current_pos : base_pos;
        }
    }

    void Draw(const std::function<void()>& content)
    {
        if (open_next_frame)
        {
            base_pos = ImGui::GetMousePos();
            current_pos = base_pos;
            ImGui::OpenPopup(label);
            open_next_frame = false;
        }

        if (ImGui::IsPopupOpen(label, ImGuiPopupFlags_AnyPopupId))
            popup_open = true;

        if (popup_open && !popup_closing)
        {
            bool clicked_outside = (ImGui::IsMouseClicked(0) || ImGui::IsMouseClicked(1))
                && !ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
            if (clicked_outside || ImGui::IsKeyPressed(ImGuiKey_Escape))
                popup_closing = true, closing_start = anim_finished && user_moved ? current_pos : base_pos;
        }

        if (popup_open)
        {
            float dt = ImGui::GetIO().DeltaTime;
            float target = popup_closing ? 0.0f : 1.0f;
            alpha = ImLerp(alpha, target, dt * alpha_speed);
            slide_t = ImLerp(slide_t, target, dt * slide_speed);
        }

        if (popup_open && popup_closing && alpha < 0.01f && slide_t < 0.01f)
        {
            ImGuiContext& g = *ImGui::GetCurrentContext();
            g.Skip_ClosePopupsOverWindow = false;
            g.Skip_ClosePopupsWhileNavUpdateCancelRequest = false;
            g.Skip_ClosePopupsCloseCurrentPopup = false;

            popup_open = false;
            popup_closing = false;
            force_close = true;
        }

        bool anim_running = (!popup_closing && slide_t < 0.99f) || (popup_closing && slide_t > 0.01f);

        if (anim_running)
        {
            ImVec2 start = popup_closing ? closing_start : base_pos;
            ImVec2 anim_pos = { start.x,start.y + slide_distance * (1.0f - slide_t) };
            ImGui::SetNextWindowPos(anim_pos, ImGuiCond_Always);
        }
        else if (!anim_finished)
        {
            ImGui::SetNextWindowPos(base_pos, ImGuiCond_Once);
            anim_finished = true;
        }

        ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);

        if (ImGui::BeginPopup(label,
            ImGuiWindowFlags_Tooltip |
            ImGuiWindowFlags_NoResize |
            ImGuiWindowFlags_NoSavedSettings |
            ImGuiWindowFlags_AlwaysAutoResize))
        {
            ImGuiContext& g = *ImGui::GetCurrentContext();
            g.Skip_ClosePopupsOverWindow = true;
            g.Skip_ClosePopupsWhileNavUpdateCancelRequest = true;
            g.Skip_ClosePopupsCloseCurrentPopup = true;

            if (anim_finished)
            {
                if (!is_dragging && ImGui::IsWindowHovered() && ImGui::IsMouseClicked(0))
                {
                    is_dragging = true;
                    drag_offset = ImGui::GetWindowPos() - ImGui::GetMousePos();
                }
                if (is_dragging)
                {
                    current_pos = ImGui::GetMousePos() + drag_offset;
                    ImGui::SetWindowPos(current_pos);
                }
                if (is_dragging && ImGui::IsMouseReleased(0))
                {
                    is_dragging = false;
                    user_moved = true;
                }
            }

            if (content) content();

            if (force_close)
            {
                g.Skip_ClosePopupsOverWindow = false;
                g.Skip_ClosePopupsWhileNavUpdateCancelRequest = false;
                g.Skip_ClosePopupsCloseCurrentPopup = false;
                ImGui::CloseCurrentPopup();
                force_close = false;
            }

            ImGui::EndPopup();
        }
        else if (!ImGui::IsPopupOpen(label, ImGuiPopupFlags_AnyPopupId))
        {
            popup_open = false;
            popup_closing = false;
            force_close = false;
            alpha = 0.0f;
            slide_t = 0.0f;
            anim_finished = false;
            is_dragging = false;
            user_moved = false;
        }

        ImGui::PopStyleVar(2);
    }
};


Как Вызывать
Код:
Expand Collapse Copy
                    {
                        /* binding box bb - new button */
                        ImVec2 text_size = ImGui::CalcTextSize(display_text);
                        ImVec2 binding_size = ImVec2(text_size.x + 2 * g.Style.FramePadding.x, text_size.y + 2 * g.Style.FramePadding.y);
                        // 12.f скорость анимации альфа канала / 13.f скорость анимации движения окна, 65 это дистанция слайда окна, имвек2 это пушстаил виндов паддинга внутри попапа впринципе не нужен но остался по наследству
                        static AnimatedPopup bind_popup(label, 15.f, 9.f, 45.f, ImVec2(8, 8));

                        if (left_pressed)
                        {
                            waiting_for_key = true;
                            current_bind = &bind;
                            open_bind_popup_next_frame = true;
                        }

                        if (left_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right))
                        {
                            bind_popup.Open();
                        }

                        bind_popup.Draw([&]() {
                            ImGui::TextFont(ui_fonts.open_sans_semi_bold_16, "change bind mode");
                            ImGui::SameLine();
                            ImGui::TextDisabled("(?)");

                            if (ImGui::IsItemHovered())
                            {
                                ImGui::BeginTooltip();
                                ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
                                ImGui::TextWrapped("list of bind mode:\n"
                                    "\uF0A7 Hold \\ the action stays active while the key is held down.\n"
                                    "\uF108 Once \\ the action triggers once when the key is pressed.\n"
                                    "\uF108 Toggle \\ the action switches on and off with each key press.\n"
                                    "\uF205 Always \\ the action remains constantly active, regardless of key presses.");
                                ImGui::PopTextWrapPos();
                                ImGui::EndTooltip();
                            }

                            ImGui::Separator();

                            if (ui_elements::tabs::TabButtonType3("\uf0A7", "Hold", bind.mode == BindMode::Hold, ImVec2(125, 21)))
                                bind.mode = BindMode::Hold;

                            if (ui_elements::tabs::TabButtonType3("\uf108", "Once", bind.mode == BindMode::Once, ImVec2(125, 21)))
                                bind.mode = BindMode::Once;

                            if (ui_elements::tabs::TabButtonType3("\uf205", "Toggle", bind.mode == BindMode::Toggle, ImVec2(125, 21)))
                                bind.mode = BindMode::Toggle;

                            if (ui_elements::tabs::TabButtonType3("\uf14a", "Always", bind.mode == BindMode::Always, ImVec2(125, 21)))
                                bind.mode = BindMode::Always;

    /*                        if (ImGui::Button("Close manually"))
                                bind_popup.Close();*/
                            });
                    }
 
Последнее редактирование:
Назад
Сверху Снизу