Cleanup - shuffle functions around (#219)

This commit is contained in:
ocornut 2015-08-06 08:11:33 -06:00
parent b6313577bb
commit f1fb62fa6d
2 changed files with 279 additions and 276 deletions

539
imgui.cpp
View File

@ -1495,22 +1495,6 @@ ImGuiWindow::~ImGuiWindow()
Name = NULL; Name = NULL;
} }
void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
{
ImGuiState& g = *GImGui;
g.ActiveId = id;
g.ActiveIdIsFocusedOnly = false;
g.ActiveIdIsJustActivated = true;
g.ActiveIdWindow = window;
}
void ImGui::KeepAliveID(ImGuiID id)
{
ImGuiState& g = *GImGui;
if (g.ActiveId == id)
g.ActiveIdIsAlive = true;
}
ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
{ {
ImGuiID seed = IDStack.back(); ImGuiID seed = IDStack.back();
@ -1527,6 +1511,10 @@ ImGuiID ImGuiWindow::GetID(const void* ptr)
return id; return id;
} }
//-----------------------------------------------------------------------------
// Internal API exposed in imgui_internal.h
//-----------------------------------------------------------------------------
ImGuiWindow* ImGui::GetCurrentWindow() ImGuiWindow* ImGui::GetCurrentWindow()
{ {
// If this ever crash it probably means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // If this ever crash it probably means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
@ -1550,6 +1538,113 @@ ImGuiWindow* ImGui::GetParentWindow()
return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2];
} }
void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
{
ImGuiState& g = *GImGui;
g.ActiveId = id;
g.ActiveIdIsFocusedOnly = false;
g.ActiveIdIsJustActivated = true;
g.ActiveIdWindow = window;
}
void ImGui::KeepAliveID(ImGuiID id)
{
ImGuiState& g = *GImGui;
if (g.ActiveId == id)
g.ActiveIdIsAlive = true;
}
// Advance cursor given item size for layout.
void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
// Always align ourselves on pixel boundaries
ImGuiState& g = *GImGui;
const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.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);
//window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, 0xFF0000FF, 4); // Debug
window->DC.PrevLineHeight = line_height;
window->DC.PrevLineTextBaseOffset = text_base_offset;
window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f;
}
void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
{
ItemSize(bb.GetSize(), text_offset_y);
}
// Declare item bounding box for clipping and interaction.
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.LastItemID = id ? *id : 0;
window->DC.LastItemRect = bb;
if (IsClippedEx(bb, id, false))
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
return false;
}
// This is a sensible default, but widgets are free to override it after calling ItemAdd()
ImGuiState& g = *GImGui;
if (IsMouseHoveringRect(bb.Min, bb.Max))
{
// Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background)
// So that clicking on items with no active id such as Text() still returns true with IsItemHovered()
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
else
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
}
return true;
}
bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (!bb.Overlaps(ImRect(window->ClipRect)))
{
if (!id || *id != GImGui->ActiveId)
if (clip_even_when_logged || !g.LogEnabled)
return true;
}
return false;
}
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
if (g.HoveredId == 0 || g.HoveredId == id)
{
ImGuiWindow* window = GetCurrentWindow();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
return false;
}
bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop)
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -1583,6 +1678,34 @@ void ImGui::FocusableItemUnregister(ImGuiWindow* window)
window->FocusIdxTabCounter--; window->FocusIdxTabCounter--;
} }
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
{
ImGuiState& g = *GImGui;
ImVec2 content_max;
if (size.x < 0.0f || size.y < 0.0f)
content_max = g.CurrentWindow->Pos + ImGui::GetContentRegionMax();
if (size.x <= 0.0f)
size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
if (size.y <= 0.0f)
size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
return size;
}
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
{
if (wrap_pos_x < 0.0f)
return 0.0f;
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (wrap_pos_x == 0.0f)
wrap_pos_x = ImGui::GetContentRegionMax().x;
if (wrap_pos_x > 0.0f)
wrap_pos_x += window->Pos.x; // wrap_pos_x is provided is window local space
const float wrap_width = wrap_pos_x > 0.0f ? ImMax(wrap_pos_x - pos.x, 0.00001f) : 0.0f;
return wrap_width;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void* ImGui::MemAlloc(size_t sz) void* ImGui::MemAlloc(size_t sz)
@ -1597,128 +1720,6 @@ void ImGui::MemFree(void* ptr)
return GImGui->IO.MemFreeFn(ptr); return GImGui->IO.MemFreeFn(ptr);
} }
static ImGuiIniData* FindWindowSettings(const char* name)
{
ImGuiState& g = *GImGui;
ImGuiID id = ImHash(name, 0);
for (int i = 0; i != g.Settings.Size; i++)
{
ImGuiIniData* ini = &g.Settings[i];
if (ini->ID == id)
return ini;
}
return NULL;
}
static ImGuiIniData* AddWindowSettings(const char* name)
{
GImGui->Settings.resize(GImGui->Settings.Size + 1);
ImGuiIniData* ini = &GImGui->Settings.back();
ini->Name = ImStrdup(name);
ini->ID = ImHash(name, 0);
ini->Collapsed = false;
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
ini->Size = ImVec2(0,0);
return ini;
}
// Zero-tolerance, poor-man .ini parsing
// FIXME: Write something less rubbish
static void LoadSettings()
{
ImGuiState& g = *GImGui;
const char* filename = g.IO.IniFilename;
if (!filename)
return;
char* file_data;
int file_size;
if (!ImLoadFileToMemory(filename, "rb", (void**)&file_data, &file_size, 1))
return;
ImGuiIniData* settings = NULL;
const char* buf_end = file_data + file_size;
for (const char* line_start = file_data; line_start < buf_end; )
{
const char* line_end = line_start;
while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
line_end++;
if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
{
char name[64];
ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1);
settings = FindWindowSettings(name);
if (!settings)
settings = AddWindowSettings(name);
}
else if (settings)
{
float x, y;
int i;
if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2)
settings->Pos = ImVec2(x, y);
else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2)
settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);
else if (sscanf(line_start, "Collapsed=%d", &i) == 1)
settings->Collapsed = (i != 0);
}
line_start = line_end+1;
}
ImGui::MemFree(file_data);
}
static void SaveSettings()
{
ImGuiState& g = *GImGui;
const char* filename = g.IO.IniFilename;
if (!filename)
return;
// Gather data from windows that were active during this session
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* window = g.Windows[i];
if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
continue;
ImGuiIniData* settings = FindWindowSettings(window->Name);
settings->Pos = window->Pos;
settings->Size = window->SizeFull;
settings->Collapsed = window->Collapsed;
}
// Write .ini file
// If a window wasn't opened in this session we preserve its settings
FILE* f = fopen(filename, "wt");
if (!f)
return;
for (int i = 0; i != g.Settings.Size; i++)
{
const ImGuiIniData* settings = &g.Settings[i];
if (settings->Pos.x == FLT_MAX)
continue;
const char* name = settings->Name;
if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
name = p;
fprintf(f, "[%s]\n", name);
fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
fprintf(f, "Collapsed=%d\n", settings->Collapsed);
fprintf(f, "\n");
}
fclose(f);
}
static void MarkSettingsDirty()
{
ImGuiState& g = *GImGui;
if (g.SettingsDirtyTimer <= 0.0f)
g.SettingsDirtyTimer = g.IO.IniSavingRate;
}
const char* ImGui::GetVersion() const char* ImGui::GetVersion()
{ {
return IMGUI_VERSION; return IMGUI_VERSION;
@ -1740,7 +1741,6 @@ void ImGui::SetInternalState(void* state, bool construct)
{ {
if (construct) if (construct)
new (state) ImGuiState(); new (state) ImGuiState();
GImGui = (ImGuiState*)state; GImGui = (ImGuiState*)state;
} }
@ -1754,6 +1754,16 @@ ImGuiStyle& ImGui::GetStyle()
return GImGui->Style; return GImGui->Style;
} }
float ImGui::GetTime()
{
return GImGui->Time;
}
int ImGui::GetFrameCount()
{
return GImGui->FrameCount;
}
void ImGui::NewFrame() void ImGui::NewFrame()
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -2005,6 +2015,128 @@ void ImGui::Shutdown()
g.Initialized = false; g.Initialized = false;
} }
static ImGuiIniData* FindWindowSettings(const char* name)
{
ImGuiState& g = *GImGui;
ImGuiID id = ImHash(name, 0);
for (int i = 0; i != g.Settings.Size; i++)
{
ImGuiIniData* ini = &g.Settings[i];
if (ini->ID == id)
return ini;
}
return NULL;
}
static ImGuiIniData* AddWindowSettings(const char* name)
{
GImGui->Settings.resize(GImGui->Settings.Size + 1);
ImGuiIniData* ini = &GImGui->Settings.back();
ini->Name = ImStrdup(name);
ini->ID = ImHash(name, 0);
ini->Collapsed = false;
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
ini->Size = ImVec2(0,0);
return ini;
}
// Zero-tolerance, poor-man .ini parsing
// FIXME: Write something less rubbish
static void LoadSettings()
{
ImGuiState& g = *GImGui;
const char* filename = g.IO.IniFilename;
if (!filename)
return;
char* file_data;
int file_size;
if (!ImLoadFileToMemory(filename, "rb", (void**)&file_data, &file_size, 1))
return;
ImGuiIniData* settings = NULL;
const char* buf_end = file_data + file_size;
for (const char* line_start = file_data; line_start < buf_end; )
{
const char* line_end = line_start;
while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
line_end++;
if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
{
char name[64];
ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1);
settings = FindWindowSettings(name);
if (!settings)
settings = AddWindowSettings(name);
}
else if (settings)
{
float x, y;
int i;
if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2)
settings->Pos = ImVec2(x, y);
else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2)
settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);
else if (sscanf(line_start, "Collapsed=%d", &i) == 1)
settings->Collapsed = (i != 0);
}
line_start = line_end+1;
}
ImGui::MemFree(file_data);
}
static void SaveSettings()
{
ImGuiState& g = *GImGui;
const char* filename = g.IO.IniFilename;
if (!filename)
return;
// Gather data from windows that were active during this session
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* window = g.Windows[i];
if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
continue;
ImGuiIniData* settings = FindWindowSettings(window->Name);
settings->Pos = window->Pos;
settings->Size = window->SizeFull;
settings->Collapsed = window->Collapsed;
}
// Write .ini file
// If a window wasn't opened in this session we preserve its settings
FILE* f = fopen(filename, "wt");
if (!f)
return;
for (int i = 0; i != g.Settings.Size; i++)
{
const ImGuiIniData* settings = &g.Settings[i];
if (settings->Pos.x == FLT_MAX)
continue;
const char* name = settings->Name;
if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
name = p;
fprintf(f, "[%s]\n", name);
fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
fprintf(f, "Collapsed=%d\n", settings->Collapsed);
fprintf(f, "\n");
}
fclose(f);
}
static void MarkSettingsDirty()
{
ImGuiState& g = *GImGui;
if (g.SettingsDirtyTimer <= 0.0f)
g.SettingsDirtyTimer = g.IO.IniSavingRate;
}
// FIXME: Add a more explicit sort order in the window structure. // FIXME: Add a more explicit sort order in the window structure.
static int ChildWindowComparer(const void* lhs, const void* rhs) static int ChildWindowComparer(const void* lhs, const void* rhs)
{ {
@ -2313,21 +2445,6 @@ static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char*
} }
} }
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
{
if (wrap_pos_x < 0.0f)
return 0.0f;
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (wrap_pos_x == 0.0f)
wrap_pos_x = ImGui::GetContentRegionMax().x;
if (wrap_pos_x > 0.0f)
wrap_pos_x += window->Pos.x; // wrap_pos_x is provided is window local space
const float wrap_width = wrap_pos_x > 0.0f ? ImMax(wrap_pos_x - pos.x, 0.00001f) : 0.0f;
return wrap_width;
}
// Internal ImGui functions to render text // Internal ImGui functions to render text
// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
@ -2820,16 +2937,6 @@ void ImGui::SetTooltip(const char* fmt, ...)
va_end(args); va_end(args);
} }
float ImGui::GetTime()
{
return GImGui->Time;
}
int ImGui::GetFrameCount()
{
return GImGui->FrameCount;
}
static ImVec4 GetVisibleRect() static ImVec4 GetVisibleRect()
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -4814,20 +4921,6 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window)
return true; return true;
} }
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
if (g.HoveredId == 0 || g.HoveredId == id)
{
ImGuiWindow* window = GetCurrentWindow();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
return false;
}
bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags) bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags)
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -4894,19 +4987,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
return pressed; return pressed;
} }
ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
{
ImGuiState& g = *GImGui;
ImVec2 content_max;
if (size.x < 0.0f || size.y < 0.0f)
content_max = g.CurrentWindow->Pos + ImGui::GetContentRegionMax();
if (size.x <= 0.0f)
size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
if (size.y <= 0.0f)
size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
return size;
}
bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -8242,48 +8322,6 @@ void ImGui::Dummy(const ImVec2& size)
ItemSize(size); ItemSize(size);
} }
// Advance cursor given item size for layout.
void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
// Always align ourselves on pixel boundaries
ImGuiState& g = *GImGui;
const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.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);
//window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, 0xFF0000FF, 4); // Debug
window->DC.PrevLineHeight = line_height;
window->DC.PrevLineTextBaseOffset = text_base_offset;
window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f;
}
void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
{
ItemSize(bb.GetSize(), text_offset_y);
}
bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (!bb.Overlaps(ImRect(window->ClipRect)))
{
if (!id || *id != GImGui->ActiveId)
if (clip_even_when_logged || !g.LogEnabled)
return true;
}
return false;
}
bool ImGui::IsRectVisible(const ImVec2& size) bool ImGui::IsRectVisible(const ImVec2& size)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -8291,41 +8329,6 @@ bool ImGui::IsRectVisible(const ImVec2& size)
return r.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); return r.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
} }
// Declare item bounding box for clipping and interaction.
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.LastItemID = id ? *id : 0;
window->DC.LastItemRect = bb;
if (IsClippedEx(bb, id, false))
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
return false;
}
// This is a sensible default, but widgets are free to override it after calling ItemAdd()
ImGuiState& g = *GImGui;
if (ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
{
// Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background)
// So that clicking on items with no active id such as Text() still returns true with IsItemHovered()
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
else
{
window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
}
return true;
}
void ImGui::BeginGroup() void ImGui::BeginGroup()
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();

View File

@ -614,9 +614,16 @@ public:
namespace ImGui namespace ImGui
{ {
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); IMGUI_API ImGuiWindow* GetCurrentWindow();
IMGUI_API ImGuiWindow* GetParentWindow();
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id);
IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged);
IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested
@ -624,13 +631,6 @@ namespace ImGui
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API ImGuiWindow* GetCurrentWindow();
IMGUI_API ImGuiWindow* GetParentWindow();
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);