Updated ImGui.

This commit is contained in:
Branimir Karadžić 2015-12-03 18:33:57 -08:00
parent cbb3f6d495
commit 488ebe2e1e
4 changed files with 191 additions and 149 deletions

View File

@ -2,7 +2,7 @@
// Main code & documentation
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Get latest version at https://github.com/ocornut/imgui
// Releases change-log at https://github.com/ocornut/imgui/releases
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
@ -76,18 +76,20 @@
- read the FAQ below this section!
- your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
- call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
- see examples/ folder for standalone sample applications. e.g. examples/opengl_example/
- see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first at it is the simplest.
- customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
- getting started:
- initialisation: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the 'Settings' data.
- init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'.
- init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory.
- every frame:
1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the 'Input' data, then call ImGui::NewFrame().
2/ use any ImGui function you want between NewFrame() and Render()
3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input'
2/ call ImGui::NewFrame().
3/ use any ImGui function you want between NewFrame() and Render()
4/ call ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
- all rendering information are stored into command-lists until ImGui::Render() is called.
- ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
- effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
- effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases.
- refer to the examples applications in the examples/ folder for instruction on how to setup your code.
- a typical application skeleton may be:
@ -100,32 +102,34 @@
// TODO: Fill others settings of the io structure
// Load texture atlas
// There is a default font so you don't need to care about choosing a font yet
unsigned char* pixels;
int width, height, bytes_per_pixels;
io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height, &bytes_per_pixels);
// TODO: copy texture to graphics memory.
// TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
int width, height;
io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);
// TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system
// TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'
// Application main loop
while (true)
{
// 1) get low-level input
// e.g. on Win32, GetKeyboardState(), or poll your events, etc.
// 2) TODO: fill all fields of IO structure and call NewFrame
// 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.)
// TODO: fill all fields of IO structure and call NewFrame
ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = 1.0f/60.0f;
io.MousePos = mouse_pos;
io.MouseDown[0] = mouse_button_0;
io.MouseDown[1] = mouse_button_1;
io.KeysDown[i] = ...
// 2) call NewFrame(), after this point you can use ImGui::* functions anytime
ImGui::NewFrame();
// 3) most of your application code here - you can use any of ImGui::* functions at any point in the frame
// 3) most of your application code here
ImGui::Begin("My window");
ImGui::Text("Hello, world.");
ImGui::End();
GameUpdate();
GameRender();
MyGameUpdate(); // may use ImGui functions
MyGameRender(); // may use ImGui functions
// 4) render & swap video buffers
ImGui::Render();
@ -410,6 +414,7 @@
- window: get size/pos helpers given names (see discussion in #249)
- window: a collapsed window can be stuck behind the main menu bar?
- window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
- window: consider renaming "GetWindowFont" which conflict with old Windows #define (#340)
- window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
- draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
!- scrolling: allow immediately effective change of scroll if we haven't appended items yet
@ -439,6 +444,8 @@
- columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
- columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
- columns: user specify columns size (#125)
- columns: flag to add horizontal separator above/below?
- columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
- combo: sparse combo boxes (via function call?)
- combo: contents should extends to fit label if combo widget is small
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
@ -475,12 +482,14 @@
- tree node / optimization: avoid formatting when clipped.
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
- tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
- settings: write more decent code to allow saving/loading new fields
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
- style: color-box not always square?
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- text: simple markup language for color change?
- font: helper to add glyph redirect/replacements (e.g. redirect alternate apostrophe unicode code points to ascii one, etc.)
- log: LogButtons() options for specifying depth and/or hiding depth slider
@ -1597,7 +1606,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
{
ImGuiState& g = *GImGui;
g.ActiveId = id;
g.ActiveIdAllowHoveringOthers = false;
g.ActiveIdAllowOverlap = false;
g.ActiveIdIsJustActivated = true;
g.ActiveIdWindow = window;
}
@ -1606,7 +1615,7 @@ void ImGui::SetHoveredID(ImGuiID id)
{
ImGuiState& g = *GImGui;
g.HoveredId = id;
g.HoveredIdAllowHoveringOthers = false;
g.HoveredIdAllowOverlap = false;
}
void ImGui::KeepAliveID(ImGuiID id)
@ -1667,7 +1676,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowHoveringOthers || (g.ActiveId == window->MoveID))
if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
@ -1696,11 +1705,11 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowHoveringOthers)
if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap)
{
ImGuiWindow* window = GetCurrentWindowRead();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowHoveringOthers) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
@ -1848,11 +1857,11 @@ void ImGui::NewFrame()
ImGuiState& g = *GImGui;
// Check user data
IM_ASSERT(g.IO.DeltaTime >= 0.0f);
IM_ASSERT(g.IO.DeltaTime >= 0.0f); // Need a positive DeltaTime (zero is tolerated but will cause some timing issues)
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
IM_ASSERT(g.IO.Fonts->Fonts.Size > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting
if (!g.Initialized)
{
@ -1928,7 +1937,7 @@ void ImGui::NewFrame()
// Clear reference to active widget if the widget isn't alive anymore
g.HoveredIdPreviousFrame = g.HoveredId;
g.HoveredId = 0;
g.HoveredIdAllowHoveringOthers = false;
g.HoveredIdAllowOverlap = false;
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
SetActiveID(0);
g.ActiveIdPreviousFrame = g.ActiveId;
@ -1982,6 +1991,7 @@ void ImGui::NewFrame()
g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
g.MouseCursor = ImGuiMouseCursor_Arrow;
g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
// If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
if (mouse_owned_by_application)
@ -2269,8 +2279,7 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDr
// If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
const unsigned long long int max_vtx_idx = (unsigned long long int)1L << (sizeof(ImDrawIdx)*8);
(void)max_vtx_idx;
IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx);
(void)max_vtx_idx;
IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx); // Too many vertices in same ImDrawList
GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
@ -2331,8 +2340,15 @@ void ImGui::EndFrame()
ImGui::EndTooltip();
}
// Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)
{
g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);
g.OsImePosSet = g.OsImePosRequest;
}
// Hide implicit "Debug" window if it hasn't been used
IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End
IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls
if (g.CurrentWindow && !g.CurrentWindow->Accessed)
g.CurrentWindow->Active = false;
ImGui::End();
@ -2368,9 +2384,8 @@ void ImGui::EndFrame()
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* window = g.Windows[i];
if (window->Flags & ImGuiWindowFlags_ChildWindow) // if a child is active its parent will add it
if (window->Active)
continue;
if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
continue;
AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
}
IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
@ -2602,6 +2617,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
}
}
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align, const ImVec2* clip_min, const ImVec2* clip_max)
{
// Hide anything after a '##' string
@ -3011,6 +3027,16 @@ bool ImGui::IsItemVisible()
return r.Overlaps(window->DC.LastItemRect);
}
// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
void ImGui::SetItemAllowOverlap()
{
ImGuiState& g = *GImGui;
if (g.HoveredId == g.CurrentWindow->DC.LastItemID)
g.HoveredIdAllowOverlap = true;
if (g.ActiveId == g.CurrentWindow->DC.LastItemID)
g.ActiveIdAllowOverlap = true;
}
ImVec2 ImGui::GetItemRectMin()
{
ImGuiWindow* window = GetCurrentWindowRead();
@ -3069,7 +3095,7 @@ void ImGui::BeginTooltip()
void ImGui::EndTooltip()
{
IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls
ImGui::End();
}
@ -3238,7 +3264,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e
void ImGui::EndPopup()
{
ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);
ImGui::End();
if (!(window->Flags & ImGuiWindowFlags_Modal))
@ -3316,7 +3342,7 @@ void ImGui::EndChild()
{
ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
{
ImGui::End();
@ -4261,7 +4287,7 @@ float ImGui::CalcItemWidth()
static void SetCurrentFont(ImFont* font)
{
ImGuiState& g = *GImGui;
IM_ASSERT(font && font->IsLoaded());
IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(font->Scale > 0.0f);
g.Font = font;
g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
@ -5533,6 +5559,7 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
return opened;
}
// FIXME: Split into CollapsingHeader(label, default_open?) and TreeNodeBehavior(label), obsolete the 4 parameters function.
bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
{
ImGuiWindow* window = GetCurrentWindow();
@ -5541,6 +5568,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
IM_ASSERT(str_id != NULL || label != NULL);
if (str_id == NULL)
@ -5548,27 +5576,27 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
if (label == NULL)
label = str_id;
const ImGuiID id = window->GetID(str_id);
// Framed header expand a little outside the default padding
const ImVec2 window_padding = window->WindowPadding;
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImVec2 pos_min = window->DC.CursorPos;
const ImVec2 pos_max = window->Pos + GetContentRegionMax();
ImRect bb = ImRect(pos_min, ImVec2(pos_max.x, pos_min.y + label_size.y));
// We vertically grow up to current line height up the typical widget height.
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y);
const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), label_size.y + padding.y*2);
ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
if (display_frame)
{
bb.Min.x -= (float)(int)(window_padding.x*0.5f) - 1;
bb.Max.x += (float)(int)(window_padding.x*0.5f) - 1;
bb.Max.y += style.FramePadding.y * 2;
// Framed header expand a little outside the default padding
bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
}
const float collapser_width = g.FontSize + style.FramePadding.x*2;
const ImRect text_bb(bb.Min, bb.Min + ImVec2(collapser_width + style.FramePadding.x*2*0 + (label_size.x > 0.0f ? label_size.x : 0.0f), label_size.y));
ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y), display_frame ? style.FramePadding.y : 0.0f);
const float collapser_width = g.FontSize + padding.x*2;
const float text_width = collapser_width + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
const ImRect interact_bb = display_frame ? bb : ImRect(text_bb.Min, text_bb.Max + ImVec2(style.FramePadding.x*2,0.0f)); // FIXME
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
// (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not)
const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y);
bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
if (!ItemAdd(interact_bb, &id))
return opened;
@ -5582,22 +5610,24 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
// Render
const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
const ImVec2 text_pos = bb.Min + padding + ImVec2(collapser_width, text_base_offset_y);
if (display_frame)
{
// Framed type
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true);
RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), opened, 1.0f, true);
if (g.LogEnabled)
{
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
const char log_prefix[] = "\n##";
LogRenderedText(bb.Min + style.FramePadding, log_prefix, log_prefix+3);
}
RenderTextClipped(bb.Min + style.FramePadding + ImVec2(collapser_width,0), bb.Max, label, NULL, &label_size);
if (g.LogEnabled)
{
const char log_suffix[] = "##";
LogRenderedText(bb.Min + style.FramePadding, log_suffix, log_suffix+2);
LogRenderedText(text_pos, log_prefix, log_prefix+3);
RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
LogRenderedText(text_pos, log_suffix+1, log_suffix+3);
}
else
{
RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
}
}
else
@ -5605,10 +5635,11 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
// Unframed typed for tree nodes
if (hovered)
RenderFrame(bb.Min, bb.Max, col, false);
RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, g.FontSize*0.15f), opened, 0.70f, false);
RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false);
if (g.LogEnabled)
LogRenderedText(bb.Min, ">");
RenderText(bb.Min + ImVec2(collapser_width,0), label);
LogRenderedText(text_pos, ">");
RenderText(text_pos, label);
}
return opened;
@ -7109,7 +7140,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
}
// Edit a string of text
// FIXME: This is rather complex partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time.
// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
{
ImGuiWindow* window = GetCurrentWindow();
@ -7128,7 +7159,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
@ -7197,7 +7228,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
{
// Start edition
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf'
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
const int prev_len_w = edit_state.CurLenW;
edit_state.Text.resize(buf_size+1); // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
@ -7205,7 +7236,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
const char* buf_end = NULL;
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
edit_state.InputCursorScreenPos = ImVec2(-1.f, -1.f);
edit_state.CursorAnimReset();
// Preserve cursor position and undo/redo stack if we come back to same widget
@ -7259,8 +7289,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
edit_state.BufSizeA = buf_size;
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner concept of focused vs active in the library.
g.ActiveIdAllowHoveringOthers = !io.MouseDown[0];
// Down the line we should have a cleaner library-wide concept of Selected vs Active.
g.ActiveIdAllowOverlap = !io.MouseDown[0];
// Edit in progress
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
@ -7407,9 +7437,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
else
{
// Apply new value immediately - copy modified buffer back
// Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
// FIXME: We actually always render 'buf' when calling DrawList->AddText
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
// Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
// FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
if (is_editable)
{
edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
@ -7624,11 +7654,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (cursor_is_visible)
draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
// Notify OS of text input position for advanced IME
if (is_editable && io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_screen_pos) > 0.0001f)
io.ImeSetInputScreenPosFn((int)cursor_screen_pos.x - 1, (int)(cursor_screen_pos.y - g.FontSize)); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
edit_state.InputCursorScreenPos = cursor_screen_pos;
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
if (is_editable)
g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
}
else
{
@ -8650,7 +8678,7 @@ void ImGui::EndGroup()
ImGuiWindow* window = GetCurrentWindow();
ImGuiStyle& style = ImGui::GetStyle();
IM_ASSERT(!window->DC.GroupStack.empty());
IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
ImGuiGroupData& group_data = window->DC.GroupStack.back();

View File

@ -226,7 +226,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
{
ImFont* font = atlas->Fonts[i];
ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
ImGui::TreePush((void*)intptr_t(i));
ImGui::TreePush((void*)(intptr_t)i);
if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } }
ImGui::PushFont(font);
ImGui::Text("The quick brown fox jumps over the lazy dog");
@ -264,7 +264,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
{
for (int i = 0; i < 5; i++)
{
if (ImGui::TreeNode((void*)intptr_t(i), "Child %d", i))
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
{
ImGui::Text("blah blah");
ImGui::SameLine();
@ -779,7 +779,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
ImGui::TreePop();
}
if (ImGui::TreeNode("Widgets Alignment"))
if (ImGui::TreeNode("Widgets Width"))
{
static float f = 0.0f;
ImGui::Text("PushItemWidth(100)");
@ -950,6 +950,17 @@ void ImGui::ShowTestWindow(bool* p_opened)
ImGui::Text("Widget"); ImGui::SameLine();
ImGui::SmallButton("Widget");
// Tree
const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
ImGui::Button("Button##1");
ImGui::SameLine(0.0f, spacing);
if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
bool tree_opened = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
if (tree_opened) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
ImGui::TreePop();
}
@ -969,7 +980,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
if (i > 0) ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
ImGui::BeginChild(ImGui::GetID((void*)intptr_t(i)), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
if (scroll_to)
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
for (int line = 0; line < 100; line++)
@ -1038,13 +1049,13 @@ void ImGui::ShowTestWindow(bool* p_opened)
static ImVec2 size(100, 100), offset(50, 20);
ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
ImGui::DragFloat2("offset", (float*)&offset, 0.5f, -200, 200.0f, "%.0f");
ImGui::TextWrapped("(Click and drag)");
ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
ImGui::GetWindowDrawList()->AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
ImGui::InvisibleButton("##dummy", size);
if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
ImGui::GetWindowDrawList()->AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
ImGui::TreePop();
}
}
@ -1328,9 +1339,9 @@ void ImGui::ShowTestWindow(bool* p_opened)
ImGui::TreePop();
}
bool opened = ImGui::TreeNode("Tree within single cell");
bool node_opened = ImGui::TreeNode("Tree within single cell");
ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell.");
if (opened)
if (node_opened)
{
ImGui::Columns(2, "tree items");
ImGui::Separator();
@ -2191,16 +2202,15 @@ static void ShowExampleAppPropertyEditor(bool* p_opened)
ImGui::Columns(2);
ImGui::Separator();
ImGui::Text("Item1"); ImGui::NextColumn();
ImGui::Text("value1"); ImGui::NextColumn();
struct funcs
{
static void ShowDummyObject(const char* prefix, ImU32 uid)
{
ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
ImGui::NextColumn();
ImGui::AlignFirstTextHeightToWidgets();
ImGui::Text("my sailor is rich");
ImGui::NextColumn();
if (opened)

View File

@ -19,7 +19,7 @@
#include <stdio.h> // vsnprintf, sscanf, printf
#include <new> // new (ptr)
#if !defined(alloca) && !defined(__FreeBSD__)
#if defined(_WIN32)
#ifdef _WIN32
#include <malloc.h> // alloca
#else
#include <alloca.h> // alloca
@ -1535,25 +1535,27 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20,
109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
};
static int ranges_unpacked = false;
static ImWchar ranges[8 + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1] =
static ImWchar base_ranges[] =
{
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF, // Half-width characters
};
if (!ranges_unpacked)
static bool full_ranges_unpacked = false;
static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1];
if (!full_ranges_unpacked)
{
// Unpack
int codepoint = 0x4e00;
ImWchar* dst = &ranges[8];
memcpy(full_ranges, base_ranges, sizeof(base_ranges));
ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);;
for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
dst[0] = 0;
ranges_unpacked = true;
full_ranges_unpacked = true;
}
return &ranges[0];
return &full_ranges[0];
}
const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()

View File

@ -196,33 +196,33 @@ enum ImGuiDataType
// NB: we can't rely on ImVec2 math operators being available here
struct IMGUI_API ImRect
{
ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right
ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right
ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {}
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
float GetWidth() const { return Max.x-Min.x; }
float GetHeight() const { return Max.y-Min.y; }
ImVec2 GetTL() const { return Min; }
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); }
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); }
ImVec2 GetBR() const { return Max; }
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; }
void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
void Round() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
float GetWidth() const { return Max.x-Min.x; }
float GetHeight() const { return Max.y-Min.y; }
ImVec2 GetTL() const { return Min; } // Top-left
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
ImVec2 GetBR() const { return Max; } // Bottom-right
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; }
void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
void Round() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
{
if (!on_edge && Contains(p))
return p;
@ -237,8 +237,8 @@ struct IMGUI_API ImRect
// Stacked color modifier, backup of modified data so we can restore it
struct ImGuiColMod
{
ImGuiCol Col;
ImVec4 PreviousValue;
ImGuiCol Col;
ImVec4 PreviousValue;
};
// Stacked style modifier, backup of modified data so we can restore it
@ -251,34 +251,34 @@ struct ImGuiStyleMod
// Stacked data for BeginGroup()/EndGroup()
struct ImGuiGroupData
{
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
float BackupIndentX;
float BackupCurrentLineHeight;
float BackupCurrentLineTextBaseOffset;
float BackupLogLinePosY;
bool AdvanceCursor;
ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos;
float BackupIndentX;
float BackupCurrentLineHeight;
float BackupCurrentLineTextBaseOffset;
float BackupLogLinePosY;
bool AdvanceCursor;
};
// Per column data for Columns()
struct ImGuiColumnData
{
float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
//float IndentX;
float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
//float IndentX;
};
// Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and NOT a generic helper.
struct IMGUI_API ImGuiSimpleColumns
{
int Count;
float Spacing;
float Width, NextWidth;
float Pos[8], NextWidths[8];
int Count;
float Spacing;
float Width, NextWidth;
float Pos[8], NextWidths[8];
ImGuiSimpleColumns();
void Update(int count, float spacing, bool clear);
float DeclColumns(float w0, float w1, float w2);
float CalcExtraSpace(float avail_w);
void Update(int count, float spacing, bool clear);
float DeclColumns(float w0, float w1, float w2);
float CalcExtraSpace(float avail_w);
};
// Internal state of the currently focused/edited text input box
@ -294,7 +294,6 @@ struct IMGUI_API ImGuiTextEditState
ImGuiStb::STB_TexteditState StbState;
float CursorAnim;
bool CursorFollow;
ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback.
bool SelectedAllMouseLock;
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
@ -309,11 +308,11 @@ struct IMGUI_API ImGuiTextEditState
// Data saved in imgui.ini file
struct ImGuiIniData
{
char* Name;
ImGuiID ID;
ImVec2 Pos;
ImVec2 Size;
bool Collapsed;
char* Name;
ImGuiID ID;
ImVec2 Pos;
ImVec2 Size;
bool Collapsed;
};
// Mouse cursor data (used when io.MouseDrawCursor is set)
@ -329,11 +328,11 @@ struct ImGuiMouseCursorData
// Storage for current popup stack
struct ImGuiPopupRef
{
ImGuiID PopupID; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* ParentWindow; // Set on OpenPopup()
ImGuiID ParentMenuSet; // Set on OpenPopup()
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
ImGuiID PopupID; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* ParentWindow; // Set on OpenPopup()
ImGuiID ParentMenuSet; // Set on OpenPopup()
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
};
@ -361,13 +360,13 @@ struct ImGuiState
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiID HoveredId; // Hovered widget
bool HoveredIdAllowHoveringOthers;
bool HoveredIdAllowOverlap;
ImGuiID HoveredIdPreviousFrame;
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdPreviousFrame;
bool ActiveIdIsAlive;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
bool ActiveIdAllowHoveringOthers; // Set only by active widget
bool ActiveIdAllowOverlap; // Set only by active widget
ImGuiWindow* ActiveIdWindow;
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
ImVector<ImGuiIniData> Settings; // .ini Settings
@ -414,6 +413,7 @@ struct ImGuiState
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
char Tooltip[1024];
char* PrivateClipboard; // If no custom clipboard handler is defined
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
// Logging
bool LogEnabled;
@ -445,13 +445,13 @@ struct ImGuiState
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredId = 0;
HoveredIdAllowHoveringOthers = false;
HoveredIdAllowOverlap = false;
HoveredIdPreviousFrame = 0;
ActiveId = 0;
ActiveIdPreviousFrame = 0;
ActiveIdIsAlive = false;
ActiveIdIsJustActivated = false;
ActiveIdAllowHoveringOthers = false;
ActiveIdAllowOverlap = false;
ActiveIdWindow = NULL;
MovedWindow = NULL;
SettingsDirtyTimer = 0.0f;
@ -477,6 +477,7 @@ struct ImGuiState
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
memset(Tooltip, 0, sizeof(Tooltip));
PrivateClipboard = NULL;
OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
ModalWindowDarkeningRatio = 0.0f;
OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
@ -682,6 +683,7 @@ namespace ImGui
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
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 void SetItemAllowOverlap(); // Allow last item to be overlapped by a subsequent item
// NB: All position are in absolute pixels coordinates (not window coordinates)
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);