- Статус
- Оффлайн
- Регистрация
- 1 Июн 2018
- Сообщения
- 704
- Реакции
- 152
1. Добавить переменные в ImGuiContext
В файле imgui_internal.h внутри структуры ImGuiContext добавляем три новых булевых переменных :
Код:
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 и анимациями
Код:
#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);
}
};
Как Вызывать
Код:
{
/* 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();*/
});
}
Последнее редактирование: