Files
dayz-dma/external/lumin/framework/widgets/helpers.cpp
T

1243 lines
43 KiB
C++

#include "../headers/functions.h"
#include "../headers/widgets.h"
void c_gui::push_color(style_col idx, ImU32 col)
{
gui_color_mod backup;
backup.col = idx;
backup.backup_value = var->style.colors[idx];
style_col_stack.push_back(backup);
var->style.colors[idx] = ColorConvertU32ToFloat4(col);
}
void c_gui::pop_color(int count)
{
while (count > 0)
{
gui_color_mod& backup = style_col_stack.back();
var->style.colors[backup.col] = backup.backup_value;
style_col_stack.pop_back();
count--;
}
}
void c_gui::push_var(style_var idx, float val)
{
const data_var_info* var_info = get_style_var_info(idx);
float* pvar = (float*)var_info->get_var_ptr(&var->style);
style_var_stack.push_back(gui_style_mod(idx, *pvar));
*pvar = val;
}
void c_gui::push_var(style_var idx, const ImVec2& val)
{
const data_var_info* var_info = get_style_var_info(idx);
ImVec2* pvar = (ImVec2*)var_info->get_var_ptr(&var->style);
style_var_stack.push_back(gui_style_mod(idx, *pvar));
*pvar = val;
}
void c_gui::pop_var(int count)
{
ImGuiContext& g = *GImGui;
while (count > 0)
{
gui_style_mod& backup = style_var_stack.back();
const data_var_info* info = get_style_var_info(backup.var_idx);
void* data = info->get_var_ptr(&var->style);
if (info->count == 1) { ((float*)data)[0] = backup.backup_float[0]; }
else if (info->count == 2) { ((float*)data)[0] = backup.backup_float[0]; ((float*)data)[1] = backup.backup_float[1]; }
style_var_stack.pop_back();
count--;
}
}
void c_gui::push_font(ImFont* font)
{
ImGuiContext& g = *GImGui;
if (font == NULL)
font = GetDefaultFont();
g.FontStack.push_back(font);
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
}
void c_gui::pop_font()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.FontStack.Size > 0);
g.FontStack.pop_back();
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
}
void c_gui::set_pos(const ImVec2& pos, int type)
{
ImGuiWindow* window = GetCurrentWindow();
if (type == pos_all)
window->DC.CursorPos = window->Pos - window->Scroll + pos;
else if (type == pos_x)
window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos.x;
else if (type == pos_y)
window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + pos.y;
window->DC.IsSetPos = true;
}
void c_gui::set_pos(float pos, int type)
{
set_pos(ImVec2(pos, pos), type);
}
ImVec2 c_gui::get_pos()
{
ImGuiWindow* window = GetCurrentWindowRead();
return window->DC.CursorPos - window->Pos + window->Scroll;
}
void c_gui::set_screen_pos(const ImVec2& pos, int type)
{
ImGuiWindow* window = GetCurrentWindow();
if (type == pos_all)
window->DC.CursorPos = pos;
else if (type == pos_x)
window->DC.CursorPos.x = pos.x;
else if (type == pos_y)
window->DC.CursorPos.y = pos.y;
window->DC.IsSetPos = true;
}
void c_gui::set_screen_pos(float pos, int type)
{
set_screen_pos(ImVec2(pos, pos), type);
}
ImVec2 c_gui::get_screen_pos()
{
ImGuiWindow* window = GetCurrentWindowRead();
return window->DC.CursorPos;
}
void c_gui::begin_group()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
g.GroupStack.resize(g.GroupStack.Size + 1);
ImGuiGroupData& group_data = g.GroupStack.back();
group_data.WindowID = window->ID;
group_data.BackupCursorPos = window->DC.CursorPos;
group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent;
group_data.BackupGroupOffset = window->DC.GroupOffset;
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupIsSameLine = window->DC.IsSameLine;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.EmitItem = true;
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
window->DC.Indent = window->DC.GroupOffset;
window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX;
}
void c_gui::end_group()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(g.GroupStack.Size > 0);
ImGuiGroupData& group_data = g.GroupStack.back();
IM_ASSERT(group_data.WindowID == window->ID);
if (window->DC.IsSetPos)
ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
ImRect group_bb(group_data.BackupCursorPos, ImMax(ImMax(window->DC.CursorMaxPos, g.LastItemData.Rect.Max), group_data.BackupCursorPos));
window->DC.CursorPos = group_data.BackupCursorPos;
window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine;
window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, group_bb.Max);
window->DC.Indent = group_data.BackupIndent;
window->DC.GroupOffset = group_data.BackupGroupOffset;
window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
window->DC.IsSameLine = group_data.BackupIsSameLine;
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX;
if (!group_data.EmitItem)
{
g.GroupStack.pop_back();
return;
}
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset);
item_size(group_bb.GetSize());
item_add(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop);
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true);
if (group_contains_curr_active_id)
g.LastItemData.ID = g.ActiveId;
else if (group_contains_prev_active_id)
g.LastItemData.ID = g.ActiveIdPreviousFrame;
g.LastItemData.Rect = group_bb;
const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
if (group_contains_curr_hovered_id)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
g.GroupStack.pop_back();
if (g.DebugShowGroupRects)
window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255, 0, 255, 255)); // [Debug]
}
void c_gui::begin_content(std::string_view id, const ImVec2& size, const ImVec2& padding, const ImVec2& spacing, window_flags window_flags__, child_flags child_flags__)
{
gui->push_var(ImGuiStyleVar_WindowPadding, padding);
gui->begin_def_child(id, size, child_flags__, window_flags__ | window_flags_no_bring_to_front_on_focus | window_flags_always_use_window_padding | window_flags_no_saved_settings | window_flags_no_focus_on_appearing);
gui->push_var(ImGuiStyleVar_ItemSpacing, spacing);
}
void c_gui::end_content()
{
gui->pop_var();
gui->end_def_child();
gui->pop_var();
}
void c_gui::sameline(float offset_from_start_x, float spacing_w)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return;
if (offset_from_start_x != 0.0f)
{
if (spacing_w < 0.0f)
spacing_w = 0.0f;
window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
}
else
{
if (spacing_w < 0.0f)
spacing_w = var->style.item_spacing.x;
window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
}
window->DC.CurrLineSize = window->DC.PrevLineSize;
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
window->DC.IsSameLine = true;
}
void c_gui::dummy(const ImVec2& size)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
gui->item_size(size);
gui->item_add(bb, 0);
}
bool begin_def_child_ex(const char* name, ImGuiID id, const ImVec2& size_arg, child_flags child_flagss, window_flags window_flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = g.CurrentWindow;
IM_ASSERT(id != 0);
const child_flags ImGuiChildFlags_SupportedMask_ = child_flags_borders | child_flags_always_use_window_padding | child_flags_resize_x | child_flags_resize_y | child_flags_auto_resize_x | child_flags_auto_resize_y | child_flags_always_auto_resize | child_flags_frame_style | child_flags_nav_flattened;
IM_UNUSED(ImGuiChildFlags_SupportedMask_);
IM_ASSERT((child_flagss & ~ImGuiChildFlags_SupportedMask_) == 0 && "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
IM_ASSERT((window_flags & window_flags_always_auto_resize) == 0 && "Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!");
if (child_flagss & child_flags_always_auto_resize)
{
IM_ASSERT((child_flagss & (child_flags_resize_x | child_flags_resize_y)) == 0 && "Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!");
IM_ASSERT((child_flagss & (child_flags_auto_resize_x | child_flags_auto_resize_y)) != 0 && "Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (window_flags & window_flags_always_use_window_padding)
child_flagss |= child_flags_always_use_window_padding;
if (window_flags & window_flags_nav_flattened)
child_flagss |= child_flags_nav_flattened;
#endif
if (child_flagss & child_flags_auto_resize_x)
child_flagss &= ~child_flags_resize_x;
if (child_flagss & child_flags_auto_resize_y)
child_flagss &= ~child_flags_resize_y;
window_flags |= window_flags_child_window | window_flags_no_title_bar;
window_flags |= (parent_window->Flags & window_flags_no_move);
if (child_flagss & (child_flags_auto_resize_x | child_flags_auto_resize_y | child_flags_always_auto_resize))
window_flags |= window_flags_always_auto_resize;
if ((child_flagss & (child_flags_resize_x | child_flags_resize_y)) == 0)
window_flags |= window_flags_no_resize | window_flags_no_saved_settings;
if (child_flagss & child_flags_frame_style)
{
PushStyleColor(style_col_child_bg, var->style.colors[ImGuiCol_FrameBg]);
PushStyleVar(style_var_child_rounding, var->style.frame_rounding);
PushStyleVar(style_var_child_border_size, var->style.frame_border_size);
PushStyleVar(style_var_window_padding, var->style.frame_padding);
child_flagss |= child_flags_border | child_flags_always_use_window_padding;
window_flags |= window_flags_no_move;
}
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
g.NextWindowData.ChildFlags = child_flagss;
const ImVec2 size_avail = GetContentRegionAvail();
const ImVec2 size_default((child_flagss & child_flags_auto_resize_x) ? 0.0f : size_avail.x, (child_flagss & child_flags_auto_resize_y) ? 0.0f : size_avail.y);
const ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
SetNextWindowSize(size);
const char* temp_window_name;
if (name)
ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%s_%08X", parent_window->Name, name, id);
else
ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%08X", parent_window->Name, id);
const float backup_border_size = var->style.child_border_size;
if ((child_flagss & child_flags_borders) == 0)
var->style.child_border_size = 0.0f;
const bool ret = gui->begin(temp_window_name, NULL, window_flags);
var->style.child_border_size = backup_border_size;
if (child_flagss & child_flags_frame_style)
{
PopStyleVar(3);
PopStyleColor();
}
ImGuiWindow* child_window = g.CurrentWindow;
child_window->ChildId = id;
if (child_window->BeginCount == 1)
parent_window->DC.CursorPos = child_window->Pos;
const ImGuiID temp_id_for_activation = ImHashStr("##Child", 0, id);
if (g.ActiveId == temp_id_for_activation)
ClearActiveID();
if (g.NavActivateId == id && !(child_flagss & child_flags_nav_flattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
{
FocusWindow(child_window);
NavInitWindow(child_window, false);
SetActiveID(temp_id_for_activation, child_window);
g.ActiveIdSource = g.NavInputSource;
}
return ret;
}
bool c_gui::begin_def_child(std::string_view name, const ImVec2& size_arg, child_flags child_flags, window_flags window_flags)
{
ImGuiID id = GetCurrentWindow()->GetID(name.data());
return begin_def_child_ex(name.data(), id, size_arg, child_flags, window_flags);
}
void c_gui::end_def_child()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* child_window = g.CurrentWindow;
IM_ASSERT(g.WithinEndChild == false);
IM_ASSERT(child_window->Flags & window_flags_child_window);
g.WithinEndChild = true;
ImVec2 child_size = child_window->Size;
gui->end();
if (child_window->BeginCount == 1)
{
ImGuiWindow* parent_window = g.CurrentWindow;
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
item_size(child_size);
const bool nav_flattened = (child_window->ChildFlags & child_flags_nav_flattened) != 0;
if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !nav_flattened)
{
item_add(bb, child_window->ChildId);
RenderNavHighlight(bb, child_window->ChildId);
if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_Compact);
}
else
{
item_add(bb, child_window->ChildId, NULL, ImGuiItemFlags_NoNav);
if (nav_flattened)
parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
}
if (g.HoveredWindow == child_window)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
}
g.WithinEndChild = false;
g.LogLinePosY = -FLT_MAX;
}
void c_gui::set_next_window_pos(const ImVec2& pos, gui_cond cond, const ImVec2& pivot)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
g.NextWindowData.PosVal = pos;
g.NextWindowData.PosPivotVal = pivot;
g.NextWindowData.PosCond = cond ? cond : gui_cond_always;
}
void c_gui::set_next_window_size(const ImVec2& size, gui_cond cond)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond));
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
g.NextWindowData.SizeVal = size;
g.NextWindowData.SizeCond = cond ? cond : gui_cond_always;
}
ImVec2 c_gui::text_size(ImFont* fontm, const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
{
this->push_font(fontm);
ImGuiContext& g = *GImGui;
const char* text_display_end;
if (hide_text_after_double_hash)
text_display_end = FindRenderedTextEnd(text, text_end);
else
text_display_end = text_end;
ImFont* font = g.Font;
const float font_size = g.FontSize;
if (text == text_display_end)
return ImVec2(0.0f, font_size);
ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
text_size.x = IM_TRUNC(text_size.x + 0.99999f);
this->pop_font();
return text_size;
}
ImVec2 c_gui::window_size()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Size;
}
float c_gui::window_width()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Size.x;
}
float c_gui::window_height()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Size.y;
}
ImVec2 c_gui::window_pos()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Pos;
}
ImDrawList* c_gui::window_drawlist()
{
ImGuiWindow* window = GetCurrentWindow();
return window->DrawList;
}
static ImDrawList* get_viewport_bg_fg_drawlist(ImGuiViewportP* viewport, size_t drawlist_no, const char* drawlist_name)
{
ImGuiContext& g = *GImGui;
// Create the draw list on demand, because they are not frequently used for all viewports
IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no];
if (draw_list == NULL)
{
draw_list = IM_NEW(ImDrawList)(&g.DrawListSharedData);
draw_list->_OwnerName = drawlist_name;
viewport->BgFgDrawLists[drawlist_no] = draw_list;
}
if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
{
draw_list->_ResetForNewFrame();
draw_list->PushTextureID(g.IO.Fonts->TexID);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
}
return draw_list;
}
ImDrawList* c_gui::foreground_drawlist()
{
ImGuiContext& g = *GImGui;
return get_viewport_bg_fg_drawlist((ImGuiViewportP*)g.Viewports[0], 1, "##Foreground");
}
ImDrawList* c_gui::background_drawlist()
{
ImGuiContext& g = *GImGui;
return get_viewport_bg_fg_drawlist((ImGuiViewportP*)g.Viewports[0], 0, "##Background");
}
ImGuiWindow* c_gui::get_window()
{
ImGuiContext& g = *GImGui;
g.CurrentWindow->WriteAccessed = true;
return g.CurrentWindow;
}
void c_gui::push_id(const char* str_id)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiID id = window->GetID(str_id);
window->IDStack.push_back(id);
}
void c_gui::push_id(const char* str_id_begin, const char* str_id_end)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiID id = window->GetID(str_id_begin, str_id_end);
window->IDStack.push_back(id);
}
void c_gui::push_id(const void* ptr_id)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiID id = window->GetID(ptr_id);
window->IDStack.push_back(id);
}
void c_gui::push_id(int int_id)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiID id = window->GetID(int_id);
window->IDStack.push_back(id);
}
void c_gui::pop_id()
{
ImGuiWindow* window = GImGui->CurrentWindow;
IM_ASSERT(window->IDStack.Size > 1);
window->IDStack.pop_back();
}
ImGuiID c_gui::get_id(const char* str, const char* str_end)
{
ImGuiID seed = get_window()->IDStack.back();
ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiContext& g = *get_window()->Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
#endif
return id;
}
ImGuiID c_gui::get_id(const void* ptr)
{
ImGuiID seed = get_window()->IDStack.back();
ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiContext& g = *get_window()->Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
#endif
return id;
}
ImGuiID c_gui::get_id(int n)
{
ImGuiID seed = get_window()->IDStack.back();
ImGuiID id = ImHashData(&n, sizeof(n), seed);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiContext& g = *get_window()->Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
#endif
return id;
}
void c_gui::item_size(const ImVec2& size, float text_baseline_y)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return;
const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
const float line_height = ImMax(window->DC.CurrLineSize.y, window->DC.CursorPos.y - line_y1 + size.y + offset_to_match_baseline_y);
window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = line_y1;
window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + var->style.item_spacing.y);
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - var->style.item_spacing.y);
window->DC.PrevLineSize.y = line_height;
window->DC.CurrLineSize.y = 0.0f;
window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
window->DC.CurrLineTextBaseOffset = 0.0f;
window->DC.IsSameLine = window->DC.IsSetPos = false;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
sameline();
}
void c_gui::item_size(const ImRect& bb, float text_baseline_y)
{
item_size(bb.GetSize(), text_baseline_y);
}
bool c_gui::item_add(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
{
return ItemAdd(bb, id, nav_bb_arg, extra_flags);
}
static ImGuiHoveredFlags apply_hover_flags_for_tooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
{
if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
return user_flags | shared_flags;
}
static ImGuiWindow* get_combined_root_window(ImGuiWindow* window, bool popup_hierarchy)
{
ImGuiWindow* last_window = NULL;
while (last_window != window)
{
last_window = window;
window = window->RootWindow;
if (popup_hierarchy)
window = window->RootWindowPopupTree;
}
return window;
}
bool c_gui::is_window_hovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 && "Invalid flags for IsWindowHovered()!");
ImGuiContext& g = *GImGui;
ImGuiWindow* ref_window = g.HoveredWindow;
ImGuiWindow* cur_window = g.CurrentWindow;
if (ref_window == NULL)
return false;
if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
{
IM_ASSERT(cur_window);
const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
if (flags & ImGuiHoveredFlags_RootWindow)
cur_window = get_combined_root_window(cur_window, popup_hierarchy);
bool result;
if (flags & ImGuiHoveredFlags_ChildWindows)
result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
else
result = (ref_window == cur_window);
if (!result)
return false;
}
if (!IsWindowContentHoverable(ref_window, flags))
return false;
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId)
return false;
if (flags & ImGuiHoveredFlags_ForTooltip)
flags = apply_hover_flags_for_tooltip(flags, var->style.hover_flags_for_tooltip_mouse);
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID)
return false;
return true;
}
bool c_gui::is_window_focused(ImGuiFocusedFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* ref_window = g.NavWindow;
ImGuiWindow* cur_window = g.CurrentWindow;
if (ref_window == NULL)
return false;
if (flags & ImGuiFocusedFlags_AnyWindow)
return true;
IM_ASSERT(cur_window);
const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
if (flags & ImGuiHoveredFlags_RootWindow)
cur_window = get_combined_root_window(cur_window, popup_hierarchy);
if (flags & ImGuiHoveredFlags_ChildWindows)
return IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
else
return (ref_window == cur_window);
}
void c_gui::set_window_focus()
{
FocusWindow(GImGui->CurrentWindow);
}
void c_gui::set_window_focus(const char* name)
{
if (name)
{
if (ImGuiWindow* window = FindWindowByName(name))
FocusWindow(window);
}
else
{
FocusWindow(NULL);
}
}
bool c_gui::is_rect_visible(const ImVec2& size)
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
}
bool c_gui::is_rect_visible(const ImRect& rect)
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->ClipRect.Overlaps(rect);
}
ImVec2 c_gui::adjust_window_pos(const ImVec2& rect, const ImVec2& window_size)
{
ImVec2 wpos = rect;
ImGuiIO& io = ImGui::GetIO();
wpos = ImClamp(wpos, ImVec2(0, 0), io.DisplaySize - window_size);
return wpos;
}
bool c_gui::button_behavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
flags |= ImGuiButtonFlags_MouseButtonLeft;
if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0)
flags |= ImGuiButtonFlags_PressedOnDefault_;
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
if (flags & ImGuiButtonFlags_AllowOverlap)
item_flags |= ImGuiItemFlags_AllowOverlap;
if (flags & ImGuiButtonFlags_Repeat)
item_flags |= ImGuiItemFlags_ButtonRepeat;
ImGuiWindow* backup_hovered_window = g.HoveredWindow;
const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
if (flatten_hovered_children)
g.HoveredWindow = window;
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (g.LastItemData.ID != id)
IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL);
#endif
bool pressed = false;
bool hovered = ItemHoverable(bb, id, item_flags);
if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
{
hovered = true;
SetHoveredID(id);
if (g.HoveredIdTimer - g.IO.DeltaTime <= 0.7f && g.HoveredIdTimer >= 0.7f)
{
pressed = true;
g.DragDropHoldJustPressedId = id;
FocusWindow(window);
}
}
if (flatten_hovered_children)
g.HoveredWindow = backup_hovered_window;
const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id;
if (hovered)
{
IM_ASSERT(id != 0);
int mouse_button_clicked = -1;
int mouse_button_released = -1;
for (int button = 0; button < 3; button++)
if (flags & (ImGuiButtonFlags_MouseButtonLeft << button))
{
if (IsMouseClicked(button, ImGuiInputFlags_None, test_owner_id) && mouse_button_clicked == -1) { mouse_button_clicked = button; }
if (IsMouseReleased(button, test_owner_id) && mouse_button_released == -1) { mouse_button_released = button; }
}
if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
{
if (mouse_button_clicked != -1 && g.ActiveId != id)
{
if (!(flags & ImGuiButtonFlags_NoSetKeyOwner))
SetKeyOwner(MouseButtonToKey(mouse_button_clicked), id);
if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere))
{
SetActiveID(id, window);
g.ActiveIdMouseButton = mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
{
SetFocusID(id, window);
FocusWindow(window);
}
else
{
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild);
}
}
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2))
{
pressed = true;
if (flags & ImGuiButtonFlags_NoHoldingActiveId)
ClearActiveID();
else
SetActiveID(id, window);
g.ActiveIdMouseButton = mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
{
SetFocusID(id, window);
FocusWindow(window);
}
else
{
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild);
}
}
}
if (flags & ImGuiButtonFlags_PressedOnRelease)
{
if (mouse_button_released != -1)
{
const bool has_repeated_at_least_once = (item_flags & ImGuiItemFlags_ButtonRepeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay; // Repeat mode trumps on release behavior
if (!has_repeated_at_least_once)
pressed = true;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
SetFocusID(id, window);
ClearActiveID();
}
}
if (g.ActiveId == id && (item_flags & ImGuiItemFlags_ButtonRepeat))
if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, ImGuiInputFlags_Repeat, test_owner_id))
pressed = true;
}
if (pressed)
g.NavDisableHighlight = true;
}
if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true;
if (g.NavActivateDownId == id)
{
bool nav_activated_by_code = (g.NavActivateId == id);
bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat))
{
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
}
if (nav_activated_by_code || nav_activated_by_inputs)
{
pressed = true;
SetActiveID(id, window);
g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut))
SetFocusID(id, window);
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)
g.ActiveIdFromShortcut = true;
}
}
bool held = false;
if (g.ActiveId == id)
{
if (g.ActiveIdSource == ImGuiInputSource_Mouse)
{
if (g.ActiveIdIsJustActivated)
g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
const int mouse_button = g.ActiveIdMouseButton;
if (mouse_button == -1)
{
ClearActiveID();
}
else if (IsMouseDown(mouse_button, test_owner_id))
{
held = true;
}
else
{
bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0;
bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0;
if ((release_in || release_anywhere) && !g.DragDropActive)
{
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2;
bool is_repeating_already = (item_flags & ImGuiItemFlags_ButtonRepeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay;
bool is_button_avail_or_owned = TestKeyOwner(MouseButtonToKey(mouse_button), test_owner_id);
if (!is_double_click_release && !is_repeating_already && is_button_avail_or_owned)
pressed = true;
}
ClearActiveID();
}
if (!(flags & ImGuiButtonFlags_NoNavFocus))
g.NavDisableHighlight = true;
}
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{
if (g.NavActivateDownId == id)
held = true;
else
ClearActiveID();
}
if (pressed)
g.ActiveIdHasBeenPressedBefore = true;
}
if (g.NavHighlightActivatedId == id)
hovered = true;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
return pressed;
}
bool c_gui::invisible_button(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
const ImGuiID id = window->GetID(str_id);
ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
item_size(size);
if (!item_add(bb, id))
return false;
bool hovered, held;
bool pressed = button_behavior(bb, id, &hovered, &held, flags);
IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
return pressed;
}
ImVec4 c_gui::u32_to_float4(ImU32 in)
{
float s = 1.0f / 255.0f;
return ImVec4(
((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
}
ImU32 c_gui::float4_to_u32(const ImVec4& in)
{
ImU32 out;
out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
return out;
}
void c_gui::rgb_to_hsv(float r, float g, float b, float& out_h, float& out_s, float& out_v)
{
float K = 0.f;
if (g < b)
{
ImSwap(g, b);
K = -1.f;
}
if (r < g)
{
ImSwap(r, g);
K = -2.f / 6.f - K;
}
const float chroma = r - (g < b ? g : b);
out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
out_s = chroma / (r + 1e-20f);
out_v = r;
}
void c_gui::hsv_to_rgb(float h, float s, float v, float& out_r, float& out_g, float& out_b)
{
if (s == 0.0f)
{
out_r = out_g = out_b = v;
return;
}
h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
int i = (int)h;
float f = h - (float)i;
float p = v * (1.0f - s);
float q = v * (1.0f - s * f);
float t = v * (1.0f - s * (1.0f - f));
switch (i)
{
case 0: out_r = v; out_g = t; out_b = p; break;
case 1: out_r = q; out_g = v; out_b = p; break;
case 2: out_r = p; out_g = v; out_b = t; break;
case 3: out_r = p; out_g = q; out_b = v; break;
case 4: out_r = t; out_g = p; out_b = v; break;
case 5: default: out_r = v; out_g = p; out_b = q; break;
}
}
bool c_gui::item_hoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (id != 0 && g.HoveredIdPreviousFrame == id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0)
{
g.HoveredIdPreviousFrameItemCount++;
if (g.DebugDrawIdConflicts == id)
window->DrawList->AddRect(bb.Min - ImVec2(1, 1), bb.Max + ImVec2(1, 1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
}
#endif
if (g.HoveredWindow != window)
return false;
if (!IsMouseHoveringRect(bb.Min, bb.Max))
return false;
if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
return false;
if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
if (!g.ActiveIdFromShortcut)
return false;
if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
{
g.HoveredIdIsDisabled = true;
return false;
}
if (id != 0)
{
if (g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
return false;
SetHoveredID(id);
if (item_flags & ImGuiItemFlags_AllowOverlap)
{
g.HoveredIdAllowOverlap = true;
if (g.HoveredIdPreviousFrame != id)
return false;
}
if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) && g.ActiveId != id)
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
SetTooltip("%s", GetKeyChordName(g.LastItemData.Shortcut));
}
if (item_flags & ImGuiItemFlags_Disabled)
{
if (g.ActiveId == id && id != 0)
ClearActiveID();
g.HoveredIdIsDisabled = true;
return false;
}
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (id != 0)
{
if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
if (g.DebugItemPickerBreakId == id)
IM_DEBUG_BREAK();
}
#endif
if (g.NavDisableMouseHover)
return false;
return true;
}
bool c_gui::is_item_hovered(ImGuiHoveredFlags flags)
{
return IsItemHovered(flags);
}
bool c_gui::is_item_active()
{
ImGuiContext& g = *GImGui;
if (g.ActiveId)
return g.ActiveId == g.LastItemData.ID;
return false;
}
bool c_gui::is_item_clicked(mouse_button mouse_button)
{
return mouse_clicked(mouse_button) && is_item_hovered(ImGuiHoveredFlags_None);
}
bool c_gui::mouse_down(mouse_button button)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
}
bool c_gui::mouse_clicked(mouse_button button, bool repeat)
{
return IsMouseClicked(button, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
}
bool c_gui::mouse_released(mouse_button button)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
}
bool c_gui::mouse_double_clicked(mouse_button button)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
}
ImVec2 c_gui::content_avail()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
return mx - window->DC.CursorPos;
}
ImVec2 c_gui::content_max()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
return mx - window->Pos;
}
const char* c_gui::text_end(const char* text)
{
const char* text_display_end = text;
const char* text_end = text + strlen(text);
while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
text_display_end++;
return text_display_end;
}
bool c_gui::is_window_cond(ImGuiWindow* window, const std::vector<std::string>& names)
{
if (window)
{
for (const auto& name : names)
{
if (strstr(window->Name, name.c_str()) != nullptr)
{
return true;
}
}
}
return false;
}
ImVec2 c_gui::mouse_pos()
{
ImGuiContext& g = *GImGui;
return g.IO.MousePos;
}
void c_gui::set_style()
{
auto* style = &var->style;
style->window_padding = s_(elements->padding);
style->item_spacing = s_(elements->padding);
style->window_border_size = 0.f;
style->window_shadow_offset = s_(0, 0);
style->window_shadow_size = 0.f;
style->scrollbar_size = s_(10.f);
style->scrollbar_content_padding = s_(10.f);
style->scrollbar_border_padding = s_(0, 0);
}
void c_gui::draw_decorations()
{
c_window* window = gui->get_window();
c_vec2 pos = window->Pos;
c_vec2 size = window->Size;
c_rect rect = c_rect(pos, pos + size);
c_draw_list* draw_list = gui->background_drawlist();
draw->rect_filled(draw_list, rect.Min, rect.Max, draw->get_clr(clr->layout), s_(elements->window.rounding));
}
void c_gui::initialize()
{
notify->setup_notify();
}
ImRect c_gui::get_item_rect()
{
return ImRect(GetItemRectMin(), GetItemRectMax());
}