From 06624bb7c2cd842ff63d0002c3fb1a1a3f1940f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 25 Aug 2015 20:44:36 -0700 Subject: [PATCH] Updated imgui. --- 3rdparty/ocornut-imgui/imgui.cpp | 300 ++++++++++-------- 3rdparty/ocornut-imgui/imgui.h | 86 ++--- 3rdparty/ocornut-imgui/imgui_demo.cpp | 87 ++--- 3rdparty/ocornut-imgui/imgui_draw.cpp | 114 ++++--- 3rdparty/ocornut-imgui/imgui_internal.h | 16 +- .../ocornut-imgui/imgui_node_graph_test.cpp | 231 ++++++++++++++ examples/common/imgui/ocornut_imgui.cpp | 12 +- 7 files changed, 566 insertions(+), 280 deletions(-) create mode 100644 3rdparty/ocornut-imgui/imgui_node_graph_test.cpp diff --git a/3rdparty/ocornut-imgui/imgui.cpp b/3rdparty/ocornut-imgui/imgui.cpp index ff23df2f..aa1ddf6e 100644 --- a/3rdparty/ocornut-imgui/imgui.cpp +++ b/3rdparty/ocornut-imgui/imgui.cpp @@ -18,13 +18,13 @@ - How do I update to a newer version of ImGui? - Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) - Why is my text output blurry? - - How can I load a different font than the default? + - How can I load a different font than the default? - How can I load multiple fonts? - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - ISSUES & TODO-LIST - CODE - + MISSION STATEMENT ================= @@ -78,11 +78,11 @@ - getting started: - initialisation: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the 'Settings' data. - - every frame: + - 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. - - all rendering information are stored into command-lists until ImGui::Render() is called. + - 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. - refer to the examples applications in the examples/ folder for instruction on how to setup your code. @@ -100,7 +100,7 @@ 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: copy texture to graphics memory. // TODO: store your texture pointer/identifier in 'io.Fonts->TexID' // Application main loop @@ -108,7 +108,7 @@ { // 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 ImGuiIO& io = ImGui::GetIO(); io.MousePos = mouse_pos; @@ -128,8 +128,10 @@ // swap video buffer, etc. } - - after calling ImGui::NewFrame() you can read back 'io.WantCaptureMouse' and 'io.WantCaptureKeyboard' to tell if ImGui - wants to use your inputs. if it does you can discard/hide the inputs from the rest of your application. + - after calling ImGui::NewFrame() you can read back flags from the IO structure to tell how ImGui intends to use your inputs. + When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. + When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an onscreen keyboard, if available. + API BREAKING CHANGES ==================== @@ -137,7 +139,7 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - + - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. @@ -145,10 +147,10 @@ - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. - - the signature of the io.RenderDrawListsFn handler has changed! + - the signature of the io.RenderDrawListsFn handler has changed! ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) became: - ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). + ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). argument 'cmd_lists' -> 'draw_data->CmdLists' argument 'cmd_lists_count' -> 'draw_data->CmdListsCount' ImDrawList 'commands' -> 'CmdBuffer' @@ -236,12 +238,12 @@ Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes) A: Yes. A primer on the use of labels/IDs in ImGui.. - + - Elements that are not clickable, such as Text() items don't need an ID. - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget). to do so they need an unique ID. unique ID are typically derived from a string label, an integer index or a pointer. - + Button("OK"); // Label = "OK", ID = hash of "OK" Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" @@ -318,7 +320,7 @@ } - when working with trees, ID are used to preserve the opened/closed state of each tree node. - depending on your use cases you may want to use strings, indices or pointers as ID. + depending on your use cases you may want to use strings, indices or pointers as ID. e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! @@ -379,7 +381,7 @@ The list below consist mostly of notes of things to do before they are requested/discussed by users (at that point it usually happens on the github) - window: autofit feedback loop when user relies on any dynamic layout (window width multiplier, column). maybe just clearly drop manual autofit? - - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. + - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. - window: allow resizing of child windows (possibly given min/max for each axis?) - window: background options for child windows, border option (disable rounding) - window: resizing from any sides? + mouse cursor directives for app. @@ -389,7 +391,7 @@ !- scrolling: allow immediately effective change of scroll if we haven't appended items yet - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. - widgets: clean up widgets internal toward exposing everything. - - widgets: add a disabled/read-only mode (#211) + - widgets: add a disabled/read-only mode (#211) - main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them. - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode? @@ -437,7 +439,7 @@ - drag float: up/down axis - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now. - text edit: centered text for slider as input text so it matches typical positioning. - - text edit: flag to disable live update of the user buffer. + - text edit: flag to disable live update of the user buffer. - text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text? - tree: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249) @@ -500,7 +502,7 @@ #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning : function xx could be declared with attribute 'noreturn' warning // GetDefaultFontData() asserts which some implementation makes it never return. #pragma clang diagnostic ignored "-Wdeprecated-declarations"// warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code) #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' @@ -818,30 +820,30 @@ int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) // Pass data_size==0 for zero-terminated strings // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImU32 ImHash(const void* data, int data_size, ImU32 seed) -{ +ImU32 ImHash(const void* data, int data_size, ImU32 seed) +{ static ImU32 crc32_lut[256] = { 0 }; if (!crc32_lut[1]) { const ImU32 polynomial = 0xEDB88320; - for (ImU32 i = 0; i < 256; i++) - { - ImU32 crc = i; - for (ImU32 j = 0; j < 8; j++) - crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial); - crc32_lut[i] = crc; + for (ImU32 i = 0; i < 256; i++) + { + ImU32 crc = i; + for (ImU32 j = 0; j < 8; j++) + crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial); + crc32_lut[i] = crc; } } seed = ~seed; - ImU32 crc = seed; + ImU32 crc = seed; const unsigned char* current = (const unsigned char*)data; if (data_size > 0) { // Known size - while (data_size--) - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++]; + while (data_size--) + crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++]; } else { @@ -850,7 +852,7 @@ ImU32 ImHash(const void* data, int data_size, ImU32 seed) { // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed. // Because this syntax is rarely used we are optimizing for the common case. - // - If we reach ### in the string we discard the hash so far and reset to the seed. + // - If we reach ### in the string we discard the hash so far and reset to the seed. // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller. if (c == '#' && current[0] == '#' && current[1] == '#') crc = seed; @@ -858,8 +860,8 @@ ImU32 ImHash(const void* data, int data_size, ImU32 seed) crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; } } - return ~crc; -} + return ~crc; +} //----------------------------------------------------------------------------- // ImText* helpers @@ -878,10 +880,10 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* *out_char = c; return 1; } - if ((*str & 0xe0) == 0xc0) + if ((*str & 0xe0) == 0xc0) { *out_char = 0; - if (in_text_end && in_text_end - (const char*)str < 2) return 0; + if (in_text_end && in_text_end - (const char*)str < 2) return 0; if (*str < 0xc2) return 0; c = (unsigned int)((*str++ & 0x1f) << 6); if ((*str & 0xc0) != 0x80) return 0; @@ -889,7 +891,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* *out_char = c; return 2; } - if ((*str & 0xf0) == 0xe0) + if ((*str & 0xf0) == 0xe0) { *out_char = 0; if (in_text_end && in_text_end - (const char*)str < 3) return 0; @@ -903,7 +905,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* *out_char = c; return 3; } - if ((*str & 0xf8) == 0xf0) + if ((*str & 0xf8) == 0xf0) { *out_char = 0; if (in_text_end && in_text_end - (const char*)str < 4) return 0; @@ -963,12 +965,12 @@ int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) // Based on stb_to_utf8() from github.com/nothings/stb/ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) { - if (c < 0x80) + if (c < 0x80) { buf[0] = (char)c; return 1; - } - if (c < 0x800) + } + if (c < 0x800) { if (buf_size < 2) return 0; buf[0] = (char)(0xc0 + (c >> 6)); @@ -978,8 +980,8 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) if (c >= 0xdc00 && c < 0xe000) { return 0; - } - if (c >= 0xd800 && c < 0xdc00) + } + if (c >= 0xd800 && c < 0xdc00) { if (buf_size < 4) return 0; buf[0] = (char)(0xf0 + (c >> 18)); @@ -1071,7 +1073,7 @@ void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 // also http://en.wikipedia.org/wiki/HSL_and_HSV void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) -{ +{ if (s == 0.0f) { // gray @@ -1364,7 +1366,7 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const // ImGuiTextBuffer //----------------------------------------------------------------------------- -// On some platform vsnprintf() takes va_list by reference and modifies it. +// On some platform vsnprintf() takes va_list by reference and modifies it. // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. #ifndef va_copy #define va_copy(dest, src) (dest = src) @@ -1404,12 +1406,12 @@ void ImGuiTextBuffer::append(const char* fmt, ...) // ImGuiSimpleColumns //----------------------------------------------------------------------------- -ImGuiSimpleColumns::ImGuiSimpleColumns() -{ - Count = 0; - Spacing = Width = NextWidth = 0.0f; - memset(Pos, 0, sizeof(Pos)); - memset(NextWidths, 0, sizeof(NextWidths)); +ImGuiSimpleColumns::ImGuiSimpleColumns() +{ + Count = 0; + Spacing = Width = NextWidth = 0.0f; + memset(Pos, 0, sizeof(Pos)); + memset(NextWidths, 0, sizeof(NextWidths)); } void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) @@ -1452,7 +1454,7 @@ float ImGuiSimpleColumns::CalcExtraSpace(float avail_w) ImGuiWindow::ImGuiWindow(const char* name) { Name = ImStrdup(name); - ID = ImHash(name, 0); + ID = ImHash(name, 0); IDStack.push_back(ID); MoveID = GetID("#MOVE"); @@ -1545,10 +1547,10 @@ ImGuiWindow* ImGui::GetParentWindow() return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; } -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) +void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) { ImGuiState& g = *GImGui; - g.ActiveId = id; + g.ActiveId = id; g.ActiveIdIsFocusedOnly = false; g.ActiveIdIsJustActivated = true; g.ActiveIdWindow = window; @@ -1585,8 +1587,8 @@ void ImGui::ItemSize(const ImVec2& size, float text_offset_y) } void ImGui::ItemSize(const ImRect& bb, float text_offset_y) -{ - ItemSize(bb.GetSize(), text_offset_y); +{ + ItemSize(bb.GetSize(), text_offset_y); } // Declare item bounding box for clipping and interaction. @@ -1901,6 +1903,7 @@ void ImGui::NewFrame() bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down]; g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (!mouse_owned_by_application && mouse_any_down) || (g.ActiveId != 0) || (!g.OpenedPopupStack.empty()) || (g.CaptureMouseNextFrame); g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (g.CaptureKeyboardNextFrame); + g.IO.WantInputCharacters = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); g.MouseCursor = ImGuiMouseCursor_Arrow; g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false; @@ -2239,11 +2242,11 @@ void ImGui::Render() const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount); g.FrameCountRendered = g.FrameCount; - + if (first_render_of_the_frame) { // 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 if (g.CurrentWindow && !g.CurrentWindow->Accessed) g.CurrentWindow->Active = false; ImGui::End(); @@ -2257,8 +2260,12 @@ void ImGui::Render() { if (g.HoveredRootWindow != NULL) { - g.MovedWindow = g.HoveredWindow; - SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow); + FocusWindow(g.HoveredWindow); + if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) + { + g.MovedWindow = g.HoveredWindow; + SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow); + } } else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) { @@ -2581,7 +2588,7 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool b = center + ImVec2(-0.500f,0.866f)*r; c = center + ImVec2(-0.500f,-0.866f)*r; } - + if (shadow && (window->Flags & ImGuiWindowFlags_ShowBorders) != 0) window->DrawList->AddTriangleFilled(a+ImVec2(2,2), b+ImVec2(2,2), c+ImVec2(2,2), window->Color(ImGuiCol_BorderShadow)); window->DrawList->AddTriangleFilled(a, b, c, window->Color(ImGuiCol_Text)); @@ -2625,7 +2632,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field) - const float font_scale = font_size / font->FontSize; + const float font_scale = font_size / font->FontSize; const float character_spacing_x = 1.0f * font_scale; if (text_size.x > 0.0f) text_size.x -= character_spacing_x; @@ -2633,7 +2640,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex return text_size; } -// Helper to calculate coarse clipping of large list of evenly sized items. +// Helper to calculate coarse clipping of large list of evenly sized items. // NB: Prefer using the ImGuiListClipper higher-level helper if you can! // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX // If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU. @@ -2826,12 +2833,13 @@ ImVec2 ImGui::GetMousePos() return GImGui->IO.MousePos; } +// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { ImGuiState& g = *GImGui; - if (g.CurrentPopupStack.Size > 0) - return g.OpenedPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; - return g.IO.MousePos; + if (g.CurrentPopupStack.Size > 0) + return g.OpenedPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; + return g.IO.MousePos; } ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) @@ -3173,7 +3181,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { ImGuiWindow* window = GetCurrentWindow(); - ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; + ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; const ImVec2 content_avail = ImGui::GetContentRegionAvail(); ImVec2 size = size_arg; @@ -3231,7 +3239,7 @@ void ImGui::EndChild() sz.x = ImMax(4.0f, sz.x - g.Style.WindowPadding.x); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) sz.y = ImMax(4.0f, sz.y - g.Style.WindowPadding.y); - + ImGui::End(); window = GetCurrentWindow(); @@ -3248,7 +3256,7 @@ bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size) const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size); + return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove); } void ImGui::EndChildFrame() @@ -3278,7 +3286,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, const ImGuiStyle& style = GImGui->Style; // Clamp into visible area while not overlapping the cursor - ImRect r_outer(GetVisibleRect()); + ImRect r_outer(GetVisibleRect()); r_outer.Reduce(style.DisplaySafeAreaPadding); ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size); @@ -3378,11 +3386,11 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl return window; } -// Push a new ImGui window to add widgets to. +// Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. // - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation. -// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). +// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. // - Passing 'bool* p_opened' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. @@ -3411,7 +3419,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window_is_new = true; } window->Flags = (ImGuiWindowFlags)flags; - + // Add to stack ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; g.CurrentWindowStack.push_back(window); @@ -3836,7 +3844,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->DC.ChildWindows.resize(0); window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ItemWidth = window->ItemWidthDefault; - window->DC.ItemWidthStack.resize(0); + window->DC.ItemWidthStack.resize(0); window->DC.ButtonRepeat = false; window->DC.ButtonRepeatStack.resize(0); window->DC.AllowKeyboardFocus = true; @@ -3867,7 +3875,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ const ImVec2 text_size = CalcTextSize(name, NULL, true); if (!(flags & ImGuiWindowFlags_NoCollapse)) RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); - + ImVec2 text_min = window->Pos + style.FramePadding; ImVec2 text_max = window->Pos + ImVec2(window->Size.x - style.FramePadding.x, style.FramePadding.y*2 + text_size.y); ImVec2 clip_max = ImVec2(window->Pos.x + window->Size.x - (p_opened ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() @@ -3898,9 +3906,11 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); - ImVec4 clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Rect().Max.x+0.5f-window->WindowPadding.x*0.5f, window->Rect().Max.y-1.5f); + ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f); + if ((flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_ShowBorders)) + clip_rect.Min += ImVec2(1.0f,1.0f); if (window->ScrollbarY) - clip_rect.z -= style.ScrollbarWidth; + clip_rect.Max.x -= style.ScrollbarWidth; PushClipRect(clip_rect); // Clear 'accessed' flag last thing @@ -4032,7 +4042,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) if (!window) return; - // And move its root window to the top of the pile + // And move its root window to the top of the pile if (window->RootWindow) window = window->RootWindow; @@ -4343,6 +4353,12 @@ float ImGui::GetWindowWidth() return window->Size.x; } +float ImGui::GetWindowHeight() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Size.y; +} + ImVec2 ImGui::GetWindowPos() { ImGuiState& g = *GImGui; @@ -4402,7 +4418,7 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond // Set if (size.x > 0.0f) { - window->AutoFitFramesX = 0; + window->AutoFitFramesX = 0; window->SizeFull.x = size.x; } else @@ -4412,7 +4428,7 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond } if (size.y > 0.0f) { - window->AutoFitFramesY = 0; + window->AutoFitFramesY = 0; window->SizeFull.y = size.y; } else @@ -4791,7 +4807,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) { // Long text! // Perform manual coarse clipping to optimize for long multi-line text - // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. + // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. const char* line = text; const float line_height = ImGui::GetTextLineHeight(); @@ -5151,7 +5167,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2); - const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); + const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size); ItemSize(bb); if (!ItemAdd(bb, &id)) return false; @@ -5256,7 +5272,7 @@ void ImGui::LogButtons() ImGui::PushID("LogButtons"); const bool log_to_tty = ImGui::Button("Log To TTY"); - ImGui::SameLine(); + ImGui::SameLine(); const bool log_to_file = ImGui::Button("Log To File"); ImGui::SameLine(); const bool log_to_clipboard = ImGui::Button("Log To Clipboard"); @@ -5420,7 +5436,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - + ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -5599,16 +5615,16 @@ static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const if (data_type == ImGuiDataType_Int) { if (op == '+') - *(int*)value1 = *(int*)value1 + *(const int*)value2; + *(int*)value1 = *(int*)value1 + *(const int*)value2; else if (op == '-') - *(int*)value1 = *(int*)value1 - *(const int*)value2; + *(int*)value1 = *(int*)value1 - *(const int*)value2; } else if (data_type == ImGuiDataType_Float) { if (op == '+') - *(float*)value1 = *(float*)value1 + *(const float*)value2; + *(float*)value1 = *(float*)value1 + *(const float*)value2; else if (op == '-') - *(float*)value1 = *(float*)value1 - *(const float*)value2; + *(float*)value1 = *(float*)value1 - *(const float*)value2; } } @@ -5636,7 +5652,7 @@ static void DataTypeApplyOpFromText(const char* buf, const char* initial_value_b if (data_type == ImGuiDataType_Int) { - if (!scalar_format) + if (!scalar_format) scalar_format = "%d"; int* v = (int*)data_ptr; int ref_v = *v; @@ -5652,7 +5668,7 @@ static void DataTypeApplyOpFromText(const char* buf, const char* initial_value_b } else if (data_type == ImGuiDataType_Float) { - if (!scalar_format) + if (!scalar_format) scalar_format = "%f"; float* v = (float*)data_ptr; float ref_v = *v; @@ -5726,7 +5742,7 @@ float ImGui::RoundScalar(float value, int decimal_precision) // Round past decimal precision // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 // FIXME: Investigate better rounding methods - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; + static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); bool negative = value < 0.0f; value = fabsf(value); @@ -6429,7 +6445,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); const int v_idx = (int)(t * (values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0))); IM_ASSERT(v_idx >= 0 && v_idx < values_count); - + const float v0 = values_getter(data, (v_idx + values_offset) % values_count); const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); if (plot_type == ImGuiPlotType_Lines) @@ -6546,7 +6562,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (*v) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), window->Color(ImGuiCol_CheckMark), style.FrameRounding); } @@ -6607,7 +6623,7 @@ bool ImGui::RadioButton(const char* label, bool active) if (active) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); - const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); + const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); window->DrawList->AddCircleFilled(center, radius-pad, window->Color(ImGuiCol_CheckMark), 16); } @@ -6725,9 +6741,9 @@ static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) obj->CurLenW -= n; // Offset remaining text - const ImWchar* src = obj->Text.Data + pos + n; + const ImWchar* src = obj->Text.Data + pos + n; while (ImWchar c = *src++) - *dst++ = c; + *dst++ = c; *dst = '\0'; } @@ -6776,10 +6792,10 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im } void ImGuiTextEditState::OnKeyPressed(int key) -{ - stb_textedit_key(this, &StbState, key); +{ + stb_textedit_key(this, &StbState, key); CursorFollow = true; - CursorAnimReset(); + CursorAnimReset(); } // Public API to manipulate UTF-8 text @@ -6861,7 +6877,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f { ImGuiTextEditCallbackData callback_data; memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); - callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; + callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; callback_data.EventChar = (ImWchar)c; callback_data.Flags = flags; callback_data.UserData = user_data; @@ -6958,7 +6974,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { edit_state.Id = id; edit_state.ScrollX = 0.f; - stb_textedit_initialize_state(&edit_state.StbState, !is_multiline); + stb_textedit_initialize_state(&edit_state.StbState, !is_multiline); if (!is_multiline && focus_requested_by_code) select_all = true; } @@ -7022,15 +7038,16 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (g.IO.InputCharacters[0]) { // Process text input (before we check for Return because using some IME will effectively send a Return?) - for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++) + if (!is_ctrl_down && !is_alt_down) { - if (unsigned int c = (unsigned int)g.IO.InputCharacters[n]) - { - // Insert character if they pass filtering - if (!InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; - edit_state.OnKeyPressed((int)c); - } + for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++) + if (unsigned int c = (unsigned int)g.IO.InputCharacters[n]) + { + // Insert character if they pass filtering + if (!InputTextFilterCharacter(&c, flags, callback, user_data)) + continue; + edit_state.OnKeyPressed((int)c); + } } // Consume characters @@ -7051,9 +7068,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !is_ctrl_down) || (!ctrl_enter_for_new_line && is_ctrl_down)) - { - SetActiveID(0); - enter_pressed = true; + { + SetActiveID(0); + enter_pressed = true; } else // New line { @@ -7168,7 +7185,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (event_key != ImGuiKey_COUNT || (flags & ImGuiInputTextFlags_CallbackAlways) != 0) { ImGuiTextEditCallbackData callback_data; - callback_data.EventFlag = event_flag; + callback_data.EventFlag = event_flag; callback_data.EventKey = event_key; callback_data.Buf = edit_state.TempTextBuffer.Data; callback_data.BufSize = edit_state.BufSizeA; @@ -7275,7 +7292,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { const float scroll_increment_x = size.x * 0.25f; if (cursor_offset.x < edit_state.ScrollX) - edit_state.ScrollX = ImMax(0.0f, cursor_offset.x - scroll_increment_x); + edit_state.ScrollX = ImMax(0.0f, cursor_offset.x - scroll_increment_x); else if (cursor_offset.x - size.x >= edit_state.ScrollX) edit_state.ScrollX = cursor_offset.x - size.x + scroll_increment_x; } @@ -7341,7 +7358,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; 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 (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. @@ -7628,7 +7645,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, window->Color(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING + RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, window->Color(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); if (*current_item >= 0 && *current_item < items_count) @@ -7640,7 +7657,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - + bool menu_toggled = false; if (hovered) { @@ -7654,13 +7671,13 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi } else { - FocusWindow(window); + FocusWindow(window); ImGui::OpenPopup(label); menu_toggled = true; } } } - + bool value_changed = false; if (IsPopupOpen(id)) { @@ -7841,7 +7858,7 @@ void ImGui::ListBoxFooter() ImGuiWindow* parent_window = GetParentWindow(); const ImRect bb = parent_window->DC.LastItemRect; const ImGuiStyle& style = ImGui::GetStyle(); - + ImGui::EndChildFrame(); // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect) @@ -7991,7 +8008,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - + ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); @@ -8053,7 +8070,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? 0x80008000 : 0x80000080); window->DrawList->PopClipRect(); // Debug } } - + want_close = (opened && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); want_open = (!opened && hovered && !moving_within_opened_triangle) || (!opened && hovered && pressed); } @@ -8184,13 +8201,13 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; - const char* fmt_table[3][4] = + const char* fmt_table[3][4] = { - { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, + { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, { "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" }, - { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } + { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } }; - const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; + const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1]; ImGui::PushItemWidth(w_item_one); for (int n = 0; n < components; n++) @@ -8218,7 +8235,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); ImGui::PopItemWidth(); char* p = buf; - while (*p == '#' || ImCharIsSpace(*p)) + while (*p == '#' || ImCharIsSpace(*p)) p++; // Treat at unsigned (%X is unsigned) @@ -8400,7 +8417,7 @@ void ImGui::SameLine(float local_pos_x, float spacing_w) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - + ImGuiState& g = *GImGui; float x, y; if (local_pos_x != 0.0f) @@ -8555,7 +8572,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ItemSize(ImVec2(0,0)); // Advance to column 0 ImGui::PopItemWidth(); PopClipRect(); - window->DrawList->ChannelsMerge(window->DC.ColumnsCount); + window->DrawList->ChannelsMerge(); window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; @@ -8745,9 +8762,9 @@ static const char* GetClipboardTextFn_DefaultImpl() ImGui::MemFree(buf_local); buf_local = NULL; } - if (!OpenClipboard(NULL)) + if (!OpenClipboard(NULL)) return NULL; - HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); + HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); if (wbuf_handle == NULL) return NULL; if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle)) @@ -8756,8 +8773,8 @@ static const char* GetClipboardTextFn_DefaultImpl() buf_local = (char*)ImGui::MemAlloc(buf_len * sizeof(char)); ImTextStrToUtf8(buf_local, buf_len, wbuf_global, NULL); } - GlobalUnlock(wbuf_handle); - CloseClipboard(); + GlobalUnlock(wbuf_handle); + CloseClipboard(); return buf_local; } @@ -8767,12 +8784,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text) return; const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; - HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); + HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); if (wbuf_handle == NULL) return; - ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); + ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); - GlobalUnlock(wbuf_handle); + GlobalUnlock(wbuf_handle); EmptyClipboard(); SetClipboardData(CF_UNICODETEXT, wbuf_handle); CloseClipboard(); @@ -8844,7 +8861,7 @@ void ImGui::ShowMetricsWindow(bool* opened) ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); static bool show_clip_rects = true; - ImGui::Checkbox("Show clipping rectangles when hovering ImDrawList", &show_clip_rects); + ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects); ImGui::Separator(); struct Funcs @@ -8875,8 +8892,8 @@ void ImGui::ShowMetricsWindow(bool* opened) for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) vtxs_rect.Add(draw_list->VtxBuffer[draw_list->IdxBuffer[i]].pos); GImGui->OverlayDrawList.PushClipRectFullScreen(); - clip_rect.Round(); GImGui->OverlayDrawList.AddRect(clip_rect.Min, clip_rect.Max, ImColor(255,255,0)); - vtxs_rect.Round(); GImGui->OverlayDrawList.AddRect(vtxs_rect.Min, vtxs_rect.Max, ImColor(255,0,255)); + clip_rect.Round(); GImGui->OverlayDrawList.AddRect(clip_rect.Min, clip_rect.Max, ImColor(255,255,0)); + vtxs_rect.Round(); GImGui->OverlayDrawList.AddRect(vtxs_rect.Min, vtxs_rect.Max, ImColor(255,0,255)); GImGui->OverlayDrawList.PopClipRect(); } } @@ -8923,6 +8940,15 @@ void ImGui::ShowMetricsWindow(bool* opened) } ImGui::TreePop(); } + if (ImGui::TreeNode("Basic state")) + { + ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); + ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); + ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); + ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); + ImGui::TreePop(); + } g.DisableHideTextAfterDoubleHash--; } ImGui::End(); diff --git a/3rdparty/ocornut-imgui/imgui.h b/3rdparty/ocornut-imgui/imgui.h index 2dab96b3..f98bb543 100644 --- a/3rdparty/ocornut-imgui/imgui.h +++ b/3rdparty/ocornut-imgui/imgui.h @@ -30,7 +30,7 @@ #define IMGUI_API #endif -#if defined(__clang__) || defined(__GNUC__) +#if defined(__clang__) || defined(__GNUC__) #define IM_PRINTFARGS(FMT) __attribute__((format(printf, FMT, (FMT+1)))) #else #define IM_PRINTFARGS(FMT) @@ -60,7 +60,7 @@ typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_ typedef int ImGuiSetCond; // enum ImGuiSetCond_ typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // enum ImGuiSelectableFlags_ -struct ImGuiTextEditCallbackData; // for advanced uses of InputText() +struct ImGuiTextEditCallbackData; // for advanced uses of InputText() typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); struct ImVec2 @@ -93,7 +93,7 @@ struct ImVec4 // - struct ImGuiStorage // Custom key value storage (if you need to alter open/close states manually) // - struct ImGuiTextEditCallbackData // Shared state of ImGui::InputText() when using custom callbacks // - struct ImGuiListClipper // Helper to manually clip large list of items. -// - struct ImColor // Helper functions to created packed 32-bit RGBA color values +// - struct ImColor // Helper functions to created packed 32-bit RGBA color values // - struct ImDrawList // Draw command list // - struct ImFontAtlas // Bake multiple fonts into a single texture, TTF font loader, bake glyphs into bitmap // - struct ImFont // Single font @@ -114,7 +114,7 @@ namespace ImGui IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging imgui // Window - IMGUI_API bool Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). + IMGUI_API bool Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually. IMGUI_API void End(); IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). @@ -131,6 +131,7 @@ namespace ImGui IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList api) IMGUI_API ImVec2 GetWindowSize(); // get current window size IMGUI_API float GetWindowWidth(); + IMGUI_API float GetWindowHeight(); IMGUI_API bool IsWindowCollapsed(); IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() @@ -177,7 +178,7 @@ namespace ImGui IMGUI_API void PopButtonRepeat(); // Cursor / Layout - IMGUI_API void BeginGroup(); // once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc. + IMGUI_API void BeginGroup(); // lock horizontal starting position. once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc. IMGUI_API void EndGroup(); IMGUI_API void Separator(); // horizontal line IMGUI_API void SameLine(float local_pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally @@ -198,7 +199,7 @@ namespace ImGui IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " IMGUI_API void SetCursorPosX(float x); // " IMGUI_API void SetCursorPosY(float y); // " - IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position + IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets @@ -228,7 +229,7 @@ namespace ImGui IMGUI_API void TextWrapped(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). IMGUI_API void TextWrappedV(const char* fmt, va_list args); IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, recommended for long chunks of text - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args); IMGUI_API void Bullet(); IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); @@ -304,7 +305,7 @@ namespace ImGui IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. // Widgets: Selectable / Lists - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); IMGUI_API bool ListBox(const char* label, int* current_item, const char** items, int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); @@ -365,7 +366,7 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowFocused(); // is current window focused + IMGUI_API bool IsWindowFocused(); // is current window focused IMGUI_API bool IsRootWindowFocused(); // is current root window focused (top parent window in case of child windows) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle of given size starting from cursor pos is visible (not clipped). to perform coarse clipping on user's side (as an optimization) @@ -389,7 +390,7 @@ namespace ImGui IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate IMGUI_API bool IsKeyReleased(int key_index); // " - IMGUI_API bool IsMouseDown(int button); // is mouse button held + IMGUI_API bool IsMouseDown(int button); // is mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) @@ -398,9 +399,9 @@ namespace ImGui IMGUI_API bool IsMouseHoveringRect(const ImVec2& pos_min, const ImVec2& pos_max); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into - IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API void ResetMouseDragDelta(int button = 0); // + IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into + IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API void ResetMouseDragDelta(int button = 0); // IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type IMGUI_API void CaptureKeyboardFromApp(); // manually enforce imgui setting the io.WantCaptureKeyboard flag next frame (your application needs to handle it). e.g. capture keyboard when your widget is being hovered. @@ -681,9 +682,9 @@ struct ImGuiIO // User Functions //------------------------------------------------------------------ - // REQUIRED: rendering function. + // REQUIRED: rendering function. // See example code if you are unsure of how to implement this. - void (*RenderDrawListsFn)(ImDrawData* data); + void (*RenderDrawListsFn)(ImDrawData* data); // Optional: access OS clipboard // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) @@ -706,7 +707,7 @@ struct ImGuiIO ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift @@ -724,6 +725,7 @@ struct ImGuiIO bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input) bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) + bool WantInputCharacters; // Some text input widget is active, which will read input characters from the InputCharacters array. float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() @@ -755,7 +757,7 @@ struct ImGuiIO // Helpers //----------------------------------------------------------------------------- -// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). +// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). // Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! template class ImVector @@ -793,14 +795,14 @@ public: inline int _grow_capacity(int new_size) { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > new_size ? new_capacity : new_size; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void reserve(int new_capacity) - { + inline void reserve(int new_capacity) + { if (new_capacity <= Capacity) return; T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); ImGui::MemFree(Data); Data = new_data; - Capacity = new_capacity; + Capacity = new_capacity; } inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } @@ -883,13 +885,13 @@ struct ImGuiTextBuffer // - You want to store custom debug data easily without adding or editing structures in your code. struct ImGuiStorage { - struct Pair - { - ImGuiID key; - union { int val_i; float val_f; void* val_p; }; - Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } - Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } - Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } + struct Pair + { + ImGuiID key; + union { int val_i; float val_f; void* val_p; }; + Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } + Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } + Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } }; ImVector Data; @@ -904,7 +906,7 @@ struct ImGuiStorage IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL IMGUI_API void SetVoidPtr(ImGuiID key, void* val); - // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. + // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. // - A typical use case where this is convenient: // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; @@ -1014,6 +1016,8 @@ struct ImDrawCmd ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. void* UserCallbackData; // The draw callback code can access this. + + ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } }; // Vertex index (override with, e.g. '#define ImDrawIdx unsigned int' in ImConfig) @@ -1037,6 +1041,7 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; #endif // Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together. +// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered. struct ImDrawChannel { ImVector CmdBuffer; @@ -1063,10 +1068,11 @@ struct ImDrawList ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImVector _ClipRectStack; // [Internal] - ImVector _TextureIdStack; // [Internal] - ImVector _Path; // [Internal] current path building - int _ChannelCurrent; // [Internal] current channel number (0) - ImVector _Channels; // [Internal] draw channels for columns API + ImVector _TextureIdStack; // [Internal] + ImVector _Path; // [Internal] current path building + int _ChannelsCurrent; // [Internal] current channel number (0) + int _ChannelsCount; // [Internal] number of active channels (1+) + ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) ImDrawList() { _OwnerName = NULL; Clear(); } ~ImDrawList() { ClearFreeMemory(); } @@ -1078,7 +1084,7 @@ struct ImDrawList IMGUI_API void PushTextureID(const ImTextureID& texture_id); IMGUI_API void PopTextureID(); - // Primitives + // Primitives IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners = 0x0F); IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners = 0x0F); @@ -1101,12 +1107,16 @@ struct ImDrawList inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } + // Channels + // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) + // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end) + IMGUI_API void ChannelsSplit(int channels_count); + IMGUI_API void ChannelsMerge(); + IMGUI_API void ChannelsSetCurrent(int channel_index); + // Advanced IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible - IMGUI_API void ChannelsSplit(int channel_count); - IMGUI_API void ChannelsMerge(int channel_count); - IMGUI_API void ChannelsSetCurrent(int idx); // Internal helpers // NB: all primitives needs to be reserved via PrimReserve() beforehand! @@ -1136,7 +1146,7 @@ struct ImFontConfig { void* FontData; // // TTF data int FontDataSize; // // TTF data size - bool FontDataOwnedByAtlas; // true // TTF data ownership taken by the container ImFontAtlas (will delete memory itself). Set to true + bool FontDataOwnedByAtlas; // true // TTF data ownership taken by the container ImFontAtlas (will delete memory itself). Set to true int FontNo; // 0 // Index of font within TTF file float SizePixels; // // Size in pixels for rasterizer int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. @@ -1145,7 +1155,7 @@ struct ImFontConfig const ImWchar* GlyphRanges; // // List of Unicode range (2 value per range, values are inclusive, zero-terminated list) bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). bool MergeGlyphCenterV; // false // When merging (multiple ImFontInput for one ImFont), vertically center new glyphs instead of aligning their baseline - + // [Internal] char Name[32]; // Name (strictly for debugging) ImFont* DstFont; diff --git a/3rdparty/ocornut-imgui/imgui_demo.cpp b/3rdparty/ocornut-imgui/imgui_demo.cpp index dfd85f3c..7ae60b2d 100644 --- a/3rdparty/ocornut-imgui/imgui_demo.cpp +++ b/3rdparty/ocornut-imgui/imgui_demo.cpp @@ -56,8 +56,8 @@ static void ShowExampleMenuFile(); static void ShowHelpMarker(const char* desc) { - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) ImGui::SetTooltip(desc); } @@ -142,7 +142,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::End(); return; } - + //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels @@ -189,7 +189,7 @@ void ImGui::ShowTestWindow(bool* opened) { ImGui::Checkbox("no titlebar", &no_titlebar); ImGui::SameLine(150); ImGui::Checkbox("no border", &no_border); ImGui::SameLine(300); - ImGui::Checkbox("no resize", &no_resize); + ImGui::Checkbox("no resize", &no_resize); ImGui::Checkbox("no move", &no_move); ImGui::SameLine(150); ImGui::Checkbox("no scrollbar", &no_scrollbar); ImGui::SameLine(300); ImGui::Checkbox("no collapse", &no_collapse); @@ -431,7 +431,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; } if (a) { - ImGui::SameLine(); + ImGui::SameLine(); ImGui::Text("Thanks for clicking me!"); } @@ -535,7 +535,7 @@ void ImGui::ShowTestWindow(bool* opened) static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; ImGui::ColorEdit3("color 1", col1); ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); - + ImGui::ColorEdit4("color 2", col2); const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; @@ -668,21 +668,21 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); static bool pause; - static ImVector values; if (values.empty()) { values.resize(90); memset(values.Data, 0, values.Size*sizeof(float)); } - static int values_offset = 0; - if (!pause) + static ImVector values; if (values.empty()) { values.resize(90); memset(values.Data, 0, values.Size*sizeof(float)); } + static int values_offset = 0; + if (!pause) { static float refresh_time = ImGui::GetTime(); // Create dummy data at fixed 60 hz rate for the demo for (; ImGui::GetTime() > refresh_time + 1.0f/60.0f; refresh_time += 1.0f/60.0f) { static float phase = 0.0f; - values[values_offset] = cosf(phase); - values_offset = (values_offset+1)%values.Size; - phase += 0.10f*values_offset; + values[values_offset] = cosf(phase); + values_offset = (values_offset+1)%values.Size; + phase += 0.10f*values_offset; } } ImGui::PlotLines("##Graph", values.Data, values.Size, values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); - ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::BeginGroup(); ImGui::Text("Graph"); ImGui::Checkbox("pause", &pause); @@ -697,7 +697,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("Without border"); static int line = 50; bool goto_line = ImGui::Button("Goto"); - ImGui::SameLine(); + ImGui::SameLine(); ImGui::PushItemWidth(100); goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); ImGui::PopItemWidth(); @@ -778,7 +778,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("can fit within a text block."); // Aligned to arbitrary position. Easy/cheap column. - ImGui::Text("Aligned"); + ImGui::Text("Aligned"); ImGui::SameLine(150); ImGui::Text("x=150"); ImGui::SameLine(300); ImGui::Text("x=300"); ImGui::Text("Aligned"); @@ -800,7 +800,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine(); ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Z", &f2, 0.0f,5.0f); + ImGui::SliderFloat("Z", &f2, 0.0f,5.0f); ImGui::PopItemWidth(); ImGui::PushItemWidth(80); @@ -812,7 +812,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PushID(i); ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); ImGui::PopID(); - //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); + //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); } ImGui::PopItemWidth(); @@ -869,9 +869,9 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Text Baseline Alignment")) { - ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); + ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)"); - ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); + ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); ImGui::Text("Hello\nWorld"); ImGui::SameLine(); ImGui::Text("Banana"); @@ -1037,8 +1037,8 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("Value = %.3f (<-- right-click here)", value); if (ImGui::BeginPopupContextItem("item context menu")) { - if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = 3.1415f; + if (ImGui::Selectable("Set to zero")) value = 0.0f; + if (ImGui::Selectable("Set to PI")) value = 3.1415f; ImGui::EndPopup(); } @@ -1058,7 +1058,7 @@ void ImGui::ShowTestWindow(bool* opened) } if (ImGui::TreeNode("Modals")) - { + { ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); if (ImGui::Button("Delete..")) @@ -1067,7 +1067,7 @@ void ImGui::ShowTestWindow(bool* opened) { ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Separator(); - + static bool dont_ask_me_next_time = false; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); @@ -1166,24 +1166,24 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Separator(); static int e = 0; - ImGui::Text("Hello"); + ImGui::Text("Hello"); ImGui::Button("Banana"); - ImGui::RadioButton("radio a", &e, 0); + ImGui::RadioButton("radio a", &e, 0); ImGui::NextColumn(); - ImGui::Text("ImGui"); + ImGui::Text("ImGui"); ImGui::Button("Apple"); ImGui::RadioButton("radio b", &e, 1); static float foo = 1.0f; - ImGui::InputFloat("red", &foo, 0.05f, 0, 3); + ImGui::InputFloat("red", &foo, 0.05f, 0, 3); ImGui::Text("An extra line here."); ImGui::NextColumn(); - + ImGui::Text("Sailor"); ImGui::Button("Corniflower"); ImGui::RadioButton("radio c", &e, 2); static float bar = 1.0f; - ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); + ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); ImGui::NextColumn(); if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); @@ -1286,11 +1286,11 @@ void ImGui::ShowTestWindow(bool* opened) bool focus_3 = ImGui::Button("Focus on 3"); int has_focus = 0; static char buf[128] = "click on a button to set focus"; - + if (focus_1) ImGui::SetKeyboardFocusHere(); ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 1; - + if (focus_2) ImGui::SetKeyboardFocusHere(); ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 2; @@ -1302,7 +1302,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PopAllowKeyboardFocus(); if (has_focus) ImGui::Text("Item with focus: %d", has_focus); - else + else ImGui::Text("Item with focus: "); ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code."); ImGui::TreePop(); @@ -1343,6 +1343,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); + ImGui::Text("WantInputCharacters: %s", io.WantInputCharacters ? "true" : "false"); ImGui::Button("Hover me\nto enforce\ninputs capture"); if (ImGui::IsItemHovered()) @@ -1360,8 +1361,8 @@ void ImGui::ShowTestWindow(bool* opened) { char label[32]; sprintf(label, "Mouse cursor %d", i); - ImGui::Bullet(); ImGui::Selectable(label, false); - if (ImGui::IsItemHovered()) + ImGui::Bullet(); ImGui::Selectable(label, false); + if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(i); } ImGui::TreePop(); @@ -1577,7 +1578,7 @@ static void ShowExampleAppFixedOverlay(bool* opened) } ImGui::Text("Simple overlay\non the top-left side of the screen."); ImGui::Separator(); - ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); + ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); ImGui::End(); } @@ -1695,14 +1696,14 @@ struct ExampleAppConsole ~ExampleAppConsole() { ClearLog(); - for (int i = 0; i < Items.Size; i++) - free(History[i]); + for (int i = 0; i < Items.Size; i++) + free(History[i]); } void ClearLog() { - for (int i = 0; i < Items.Size; i++) - free(Items[i]); + for (int i = 0; i < Items.Size; i++) + free(Items[i]); Items.clear(); ScrollToBottom = true; } @@ -1733,8 +1734,8 @@ struct ExampleAppConsole // TODO: display items starting from the bottom - if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); - if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); if (ImGui::SmallButton("Clear")) ClearLog(); //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } @@ -2053,7 +2054,7 @@ static void ShowExampleAppLayout(bool* opened) } ImGui::EndChild(); ImGui::SameLine(); - + // right ImGui::BeginGroup(); ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us @@ -2084,7 +2085,7 @@ static void ShowExampleAppLongText(bool* opened) static ImGuiTextBuffer log; static int lines = 0; ImGui::Text("Printing unusually long amount of text."); - ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); + ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); if (ImGui::Button("Clear")) { log.clear(); lines = 0; } ImGui::SameLine(); diff --git a/3rdparty/ocornut-imgui/imgui_draw.cpp b/3rdparty/ocornut-imgui/imgui_draw.cpp index 4cc60f9d..0d3e411b 100644 --- a/3rdparty/ocornut-imgui/imgui_draw.cpp +++ b/3rdparty/ocornut-imgui/imgui_draw.cpp @@ -85,7 +85,7 @@ using namespace IMGUI_STB_NAMESPACE; // ImDrawList //----------------------------------------------------------------------------- -static ImVec4 GNullClipRect(-9999.0f,-9999.0f, +9999.0f, +9999.0f); +static ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift void ImDrawList::Clear() { @@ -98,7 +98,8 @@ void ImDrawList::Clear() _ClipRectStack.resize(0); _TextureIdStack.resize(0); _Path.resize(0); - _ChannelCurrent = 0; + _ChannelsCurrent = 0; + _ChannelsCount = 1; // NB: Do not clear channels so our allocations are re-used after the first frame. } @@ -113,7 +114,8 @@ void ImDrawList::ClearFreeMemory() _ClipRectStack.clear(); _TextureIdStack.clear(); _Path.clear(); - _ChannelCurrent = 0; + _ChannelsCurrent = 0; + _ChannelsCount = 1; for (int i = 0; i < _Channels.Size; i++) { if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0])); // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again @@ -126,11 +128,8 @@ void ImDrawList::ClearFreeMemory() void ImDrawList::AddDrawCmd() { ImDrawCmd draw_cmd; - draw_cmd.ElemCount = 0; draw_cmd.ClipRect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect; draw_cmd.TextureId = _TextureIdStack.Size ? _TextureIdStack.back() : NULL; - draw_cmd.UserCallback = NULL; - draw_cmd.UserCallbackData = NULL; IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w); CmdBuffer.push_back(draw_cmd); @@ -151,32 +150,42 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) AddDrawCmd(); } -void ImDrawList::ChannelsSplit(int channel_count) +void ImDrawList::ChannelsSplit(int channels_count) { - IM_ASSERT(_ChannelCurrent == 0); + IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1); int old_channels_count = _Channels.Size; - if (old_channels_count < channel_count) - _Channels.resize(channel_count); - for (int i = 0; i < channel_count; i++) + if (old_channels_count < channels_count) + _Channels.resize(channels_count); + _ChannelsCount = channels_count; + for (int i = 0; i < channels_count; i++) + { if (i >= old_channels_count) new(&_Channels[i]) ImDrawChannel(); - else + else if (i > 0) _Channels[i].CmdBuffer.resize(0), _Channels[i].IdxBuffer.resize(0); + if (_Channels[i].CmdBuffer.Size == 0) + { + ImDrawCmd draw_cmd; + draw_cmd.ClipRect = _ClipRectStack.back(); + draw_cmd.TextureId = _TextureIdStack.back(); + _Channels[i].CmdBuffer.push_back(draw_cmd); + } + } } -void ImDrawList::ChannelsMerge(int channel_count) +void ImDrawList::ChannelsMerge() { // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use. // This is why this function takes 'channel_count' as a parameter of how many channels to merge (the user knows) - if (channel_count < 2) + if (_ChannelsCount <= 1) return; ChannelsSetCurrent(0); - if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0) + if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0) CmdBuffer.pop_back(); int new_cmd_buffer_count = 0, new_idx_buffer_count = 0; - for (int i = 1; i < channel_count; i++) + for (int i = 1; i < _ChannelsCount; i++) { ImDrawChannel& ch = _Channels[i]; if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0) @@ -189,23 +198,24 @@ void ImDrawList::ChannelsMerge(int channel_count) ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count; _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count; - for (int i = 1; i < channel_count; i++) + for (int i = 1; i < _ChannelsCount; i++) { ImDrawChannel& ch = _Channels[i]; if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; } } AddDrawCmd(); + _ChannelsCount = 1; } void ImDrawList::ChannelsSetCurrent(int idx) { - if (_ChannelCurrent == idx) return; - memcpy(&_Channels.Data[_ChannelCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); - memcpy(&_Channels.Data[_ChannelCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer)); - _ChannelCurrent = idx; - memcpy(&CmdBuffer, &_Channels.Data[_ChannelCurrent].CmdBuffer, sizeof(CmdBuffer)); - memcpy(&IdxBuffer, &_Channels.Data[_ChannelCurrent].IdxBuffer, sizeof(IdxBuffer)); + if (_ChannelsCurrent == idx) return; + memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); // copy 12 bytes, four times + memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer)); + _ChannelsCurrent = idx; + memcpy(&CmdBuffer, &_Channels.Data[_ChannelsCurrent].CmdBuffer, sizeof(CmdBuffer)); + memcpy(&IdxBuffer, &_Channels.Data[_ChannelsCurrent].IdxBuffer, sizeof(IdxBuffer)); _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size; } @@ -292,11 +302,11 @@ void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) const ImVec2 uv = GImGui->FontTexUvWhitePixel; const ImVec2 b(c.x, a.y); const ImVec2 d(a.x, c.y); - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); - _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); + _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); + _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; @@ -309,11 +319,11 @@ void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a const ImVec2 d(a.x, c.y); const ImVec2 uv_b(uv_c.x, uv_a.y); const ImVec2 uv_d(uv_a.x, uv_c.y); - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); - _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); + _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); + _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; + _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; + _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; @@ -351,7 +361,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; + const int i2 = (i1+1) == points_count ? 0 : i1+1; ImVec2 diff = points[i2] - points[i1]; diff *= ImInvLength(diff, 1.0f); temp_normals[i1].x = diff.y; @@ -428,7 +438,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 unsigned int idx1 = _VtxCurrentIdx; for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; + const int i2 = (i1+1) == points_count ? 0 : i1+1; unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4; // Average normals @@ -480,7 +490,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 for (int i1 = 0; i1 < count; i1++) { - const int i2 = (i1+1) == points_count ? 0 : i1+1; + const int i2 = (i1+1) == points_count ? 0 : i1+1; const ImVec2& p1 = points[i1]; const ImVec2& p2 = points[i2]; ImVec2 diff = p2 - p1; @@ -494,8 +504,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); - _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2); + _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3); _IdxWritePtr += 6; _VtxCurrentIdx += 4; } @@ -578,7 +588,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun } for (int i = 2; i < points_count; i++) { - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i); + _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i); _IdxWritePtr += 3; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; @@ -900,7 +910,7 @@ void ImFontAtlas::ClearFonts() void ImFontAtlas::Clear() { - ClearInputData(); + ClearInputData(); ClearTexData(); ClearFonts(); } @@ -1005,7 +1015,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); if (font_cfg.Name[0] == '\0') { - const char* p; + const char* p; for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s", p); } @@ -1016,7 +1026,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - IM_ASSERT(font_cfg.FontData == NULL); + IM_ASSERT(font_cfg.FontData == NULL); font_cfg.FontData = ttf_data; font_cfg.FontDataSize = ttf_size; font_cfg.SizePixels = size_pixels; @@ -1032,7 +1042,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - IM_ASSERT(font_cfg.FontData == NULL); + IM_ASSERT(font_cfg.FontData == NULL); font_cfg.FontDataOwnedByAtlas = true; return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, font_cfg_template, glyph_ranges); } @@ -1076,7 +1086,7 @@ bool ImFontAtlas::Build() IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == this)); const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0); - if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) + if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) return false; if (!cfg.GlyphRanges) @@ -1226,7 +1236,7 @@ bool ImFontAtlas::Build() dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1); ImFont::Glyph& glyph = dst_font->Glyphs.back(); glyph.Codepoint = (ImWchar)codepoint; - glyph.X0 = q.x0; glyph.Y0 = q.y0; glyph.X1 = q.x1; glyph.Y1 = q.y1; + glyph.X0 = q.x0; glyph.Y0 = q.y0; glyph.X1 = q.x1; glyph.Y1 = q.y1; glyph.U0 = q.s0; glyph.V0 = q.t0; glyph.U1 = q.s1; glyph.V1 = q.t1; glyph.Y0 += (float)(int)(dst_font->Ascent + off_y + 0.5f); glyph.Y1 += (float)(int)(dst_font->Ascent + off_y + 0.5f); @@ -1367,7 +1377,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() { // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1. // This encoding helps us reduce the source code size. - static const short offsets_from_0x4E00[] = + static const short offsets_from_0x4E00[] = { -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17, 4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1, @@ -1867,8 +1877,8 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re // NB: we are not calling PrimRectUV() here because non-inlined causes too much overhead in a debug build. // inlined: { - idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); - idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); + idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); + idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; @@ -2002,7 +2012,7 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi return 0; } } - IM_ASSERT(stb__dout <= output + olen); + IM_ASSERT(stb__dout <= output + olen); if (stb__dout > output + olen) return 0; } @@ -2105,7 +2115,7 @@ static const char proggy_clean_ttf_compressed_data_base85[11980+1] = "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; -static const char* GetDefaultCompressedFontDataTTFBase85() -{ - return proggy_clean_ttf_compressed_data_base85; +static const char* GetDefaultCompressedFontDataTTFBase85() +{ + return proggy_clean_ttf_compressed_data_base85; } diff --git a/3rdparty/ocornut-imgui/imgui_internal.h b/3rdparty/ocornut-imgui/imgui_internal.h index 8c9b8ab2..73255bcc 100644 --- a/3rdparty/ocornut-imgui/imgui_internal.h +++ b/3rdparty/ocornut-imgui/imgui_internal.h @@ -81,7 +81,7 @@ int ImTextCountCharsFromUtf8(const char* in_text, const char* in int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points // Helpers: Misc -ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings +ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, int* out_file_size = NULL, int padding_bytes = 0); bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c); static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; } @@ -201,7 +201,7 @@ struct ImRect 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; } + 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)) @@ -305,7 +305,7 @@ struct ImGuiPopupRef 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 + 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; } }; @@ -383,7 +383,7 @@ struct ImGuiState // Logging bool LogEnabled; - FILE* LogFile; // If != NULL log to stdout/ file + FILE* LogFile; // If != NULL log to stdout/ file ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. int LogStartDepth; int LogAutoExpandMaxDepth; @@ -563,14 +563,14 @@ struct ImGuiWindow bool Collapsed; // Set when collapsing window to become only title-bar bool SkipItems; // == Visible && !Collapsed int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) - ImGuiID PopupID; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) + ImGuiID PopupID; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; int AutoPosLastDirection; int HiddenFrames; - int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. - int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. - int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. + int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. + int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. + int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. bool SetWindowPosCenterWanted; ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame diff --git a/3rdparty/ocornut-imgui/imgui_node_graph_test.cpp b/3rdparty/ocornut-imgui/imgui_node_graph_test.cpp new file mode 100644 index 00000000..e3560293 --- /dev/null +++ b/3rdparty/ocornut-imgui/imgui_node_graph_test.cpp @@ -0,0 +1,231 @@ +// Creating a node graph editor for ImGui +// Quick demo, not production code! +// See https://github.com/ocornut/imgui/issues/306 +// v0.01 +// Animated gif: https://cloud.githubusercontent.com/assets/8225057/9472357/c0263c04-4b4c-11e5-9fdf-2cd4f33f6582.gif + +#include +#include "imgui.h" + +// NB: You can use math functions/operators on ImVec2 if you #define IMGUI_DEFINE_MATH_OPERATORS and #include "imgui_internal.h" +// Here we only declare simple +/- operators so others don't leak into the demo code. +static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); } +static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } + +// Really dumb data structure provided for the example. +// Note that we storing links are INDICES (not ID) to make example code shorter, obviously a bad idea for any general purpose code. +void ShowExampleAppCustomNodeGraph(bool* opened) +{ + ImGui::SetNextWindowSize(ImVec2(700,600), ImGuiSetCond_FirstUseEver); + if (!ImGui::Begin("Example: Custom Node Graph", opened)) + { + ImGui::End(); + return; + } + + struct Node + { + int ID; + char Name[32]; + ImVec2 Pos, Size; + float Value; + int InputsCount, OutputsCount; + + Node(int id, const char* name, const ImVec2& pos, float value, int inputs_count, int outputs_count) { ID = id; strncpy(Name, name, 31); Name[31] = 0; Pos = pos; Value = value; InputsCount = inputs_count; OutputsCount = outputs_count; } + + ImVec2 GetInputSlotPos(int slot_no) const { return ImVec2(Pos.x, Pos.y + Size.y * ((float)slot_no+1) / ((float)InputsCount+1)); } + ImVec2 GetOutputSlotPos(int slot_no) const { return ImVec2(Pos.x + Size.x, Pos.y + Size.y * ((float)slot_no+1) / ((float)OutputsCount+1)); } + }; + struct NodeLink + { + int InputIdx, InputSlot, OutputIdx, OutputSlot; + + NodeLink(int input_idx, int input_slot, int output_idx, int output_slot) { InputIdx = input_idx; InputSlot = input_slot; OutputIdx = output_idx; OutputSlot = output_slot; } + }; + + static ImVector nodes; + static ImVector links; + static bool inited = false; + static ImVec2 scrolling = ImVec2(0.0f, 0.0f); + static int node_selected = -1; + if (!inited) + { + nodes.push_back(Node(0, "MainTex", ImVec2(40,50), 0.5f, 1, 1)); + nodes.push_back(Node(1, "BumpMap", ImVec2(40,150), 0.42f, 1, 1)); + nodes.push_back(Node(2, "Combine", ImVec2(270,80), 1.0f, 2, 2)); + links.push_back(NodeLink(0, 0, 2, 0)); + links.push_back(NodeLink(1, 0, 2, 1)); + inited = true; + } + + // Draw a list of nodes on the left side + bool open_context_menu = false; + int node_hovered_in_list = -1; + int node_hovered_in_scene = -1; + ImGui::BeginChild("node_list", ImVec2(100,0)); + ImGui::Text("Nodes"); + ImGui::Separator(); + for (int node_idx = 0; node_idx < nodes.Size; node_idx++) + { + Node* node = &nodes[node_idx]; + ImGui::PushID(node->ID); + if (ImGui::Selectable(node->Name, node->ID == node_selected)) + node_selected = node->ID; + if (ImGui::IsItemHovered()) + { + node_hovered_in_list = node->ID; + open_context_menu |= ImGui::IsMouseClicked(1); + } + ImGui::PopID(); + } + ImGui::EndChild(); + + ImGui::SameLine(); + ImGui::BeginGroup(); + + const float NODE_SLOT_RADIUS = 4.0f; + const ImVec2 NODE_WINDOW_PADDING(8.0f, 8.0f); + + // Create our child canvas + ImGui::Text("Hold middle mouse button to scroll (%.2f,%.2f)", scrolling.x, scrolling.y); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1,1)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); + ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(40,40,40,200)); + ImGui::BeginChild("scrolling_region", ImVec2(0,0), true, ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoMove); + ImGui::PushItemWidth(120.0f); + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->ChannelsSplit(2); + ImVec2 offset = ImGui::GetCursorScreenPos() - scrolling; + + // Display links + draw_list->ChannelsSetCurrent(0); // Background + for (int link_idx = 0; link_idx < links.Size; link_idx++) + { + NodeLink* link = &links[link_idx]; + Node* node_inp = &nodes[link->InputIdx]; + Node* node_out = &nodes[link->OutputIdx]; + +#if 1 + // Hermite spline + // TODO: move to ImDrawList path API + ImVec2 p1 = offset+node_inp->GetOutputSlotPos(link->InputSlot); + ImVec2 t1 = ImVec2(+80.0f, 0.0f); + ImVec2 p2 = offset+node_out->GetInputSlotPos(link->OutputSlot); + ImVec2 t2 = ImVec2(+80.0f, 0.0f); + const int STEPS = 12; + for (int step = 0; step <= STEPS; step++) + { + float t = (float)step / (float)STEPS; + float h1 = +2*t*t*t - 3*t*t + 1.0f; + float h2 = -2*t*t*t + 3*t*t; + float h3 = t*t*t - 2*t*t + t; + float h4 = t*t*t - t*t; + draw_list->PathLineTo(ImVec2(h1*p1.x + h2*p2.x + h3*t1.x + h4*t2.x, h1*p1.y + h2*p2.y + h3*t1.y + h4*t2.y)); + } + draw_list->PathStroke(ImColor(200,200,100), false, 3.0f); +#else + draw_list->AddLine(offset+node_inp->GetOutputSlotPos(link->InputSlot), offset+node_out->GetInputSlotPos(link->OutputSlot), ImColor(200,200,100), 3.0f); +#endif + } + + // Display nodes + for (int node_idx = 0; node_idx < nodes.Size; node_idx++) + { + Node* node = &nodes[node_idx]; + ImGui::PushID(node->ID); + ImVec2 node_rect_min = offset + node->Pos; + + // Display node contents first + draw_list->ChannelsSetCurrent(1); // Foreground + bool old_any_active = ImGui::IsAnyItemActive(); + ImGui::SetCursorScreenPos(node_rect_min + NODE_WINDOW_PADDING); + ImGui::BeginGroup(); // Lock horizontal position + ImGui::Text("%s", node->Name); + ImGui::SliderFloat("##value", &node->Value, 0.0f, 1.0f, "Alpha %.2f"); + float dummy_color[3] = { node->Pos.x / ImGui::GetWindowWidth(), node->Pos.y / ImGui::GetWindowHeight(), fmodf((float)node->ID * 0.5f, 1.0f) }; + ImGui::ColorEdit3("##color", &dummy_color[0]); + ImGui::EndGroup(); + + // Save the size of what we have emitted and weither any of the widgets are being used + bool node_widgets_active = (!old_any_active && ImGui::IsAnyItemActive()); + node->Size = ImGui::GetItemRectSize() + NODE_WINDOW_PADDING + NODE_WINDOW_PADDING; + ImVec2 node_rect_max = node_rect_min + node->Size; + + // Display node box + draw_list->ChannelsSetCurrent(0); // Background + ImGui::SetCursorScreenPos(node_rect_min); + ImGui::InvisibleButton("node", node->Size); + if (ImGui::IsItemHovered()) + { + node_hovered_in_scene = node->ID; + open_context_menu |= ImGui::IsMouseClicked(1); + } + bool node_moving_active = ImGui::IsItemActive(); + if (node_widgets_active || node_moving_active) + node_selected = node->ID; + if (node_moving_active && ImGui::IsMouseDragging(0)) + node->Pos = node->Pos + ImGui::GetIO().MouseDelta; + + ImU32 node_bg_color = (node_hovered_in_list == node->ID || node_hovered_in_scene == node->ID || (node_hovered_in_list == -1 && node_selected == node->ID)) ? ImColor(75,75,75) : ImColor(60,60,60); + draw_list->AddRectFilled(node_rect_min, node_rect_max, node_bg_color, 4.0f); + draw_list->AddRect(node_rect_min, node_rect_max, ImColor(100,100,100), 4.0f); + for (int slot_idx = 0; slot_idx < node->InputsCount; slot_idx++) + draw_list->AddCircleFilled(offset + node->GetInputSlotPos(slot_idx), NODE_SLOT_RADIUS, ImColor(150,150,150,150)); + for (int slot_idx = 0; slot_idx < node->OutputsCount; slot_idx++) + draw_list->AddCircleFilled(offset + node->GetOutputSlotPos(slot_idx), NODE_SLOT_RADIUS, ImColor(150,150,150,150)); + + ImGui::PopID(); + } + draw_list->ChannelsMerge(); + + // Open context menu + if (!ImGui::IsAnyItemHovered() && ImGui::IsMouseHoveringWindow() && ImGui::IsMouseClicked(1)) + { + node_selected = node_hovered_in_list = node_hovered_in_scene = -1; + open_context_menu = true; + } + if (open_context_menu) + { + ImGui::OpenPopup("context_menu"); + if (node_hovered_in_list != -1) + node_selected = node_hovered_in_list; + if (node_hovered_in_scene != -1) + node_selected = node_hovered_in_scene; + } + + // Draw context menu + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8,8)); + if (ImGui::BeginPopup("context_menu")) + { + Node* node = node_selected != -1 ? &nodes[node_selected] : NULL; + ImVec2 scene_pos = ImGui::GetMousePosOnOpeningCurrentPopup() - offset; + if (node) + { + ImGui::Text("Node '%s'", node->Name); + ImGui::Separator(); + if (ImGui::MenuItem("Rename..", NULL, false, false)) {} + if (ImGui::MenuItem("Delete", NULL, false, false)) {} + if (ImGui::MenuItem("Copy", NULL, false, false)) {} + } + else + { + if (ImGui::MenuItem("Add")) { nodes.push_back(Node(nodes.Size, "New node", scene_pos, 0.5f, 2, 2)); } + if (ImGui::MenuItem("Paste", NULL, false, false)) {} + } + ImGui::EndPopup(); + } + ImGui::PopStyleVar(); + + // Scrolling + if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f)) + scrolling = scrolling - ImGui::GetIO().MouseDelta; + + ImGui::PopItemWidth(); + ImGui::EndChild(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + ImGui::EndGroup(); + + ImGui::End(); +} diff --git a/examples/common/imgui/ocornut_imgui.cpp b/examples/common/imgui/ocornut_imgui.cpp index ad6997c0..33ad44ae 100644 --- a/examples/common/imgui/ocornut_imgui.cpp +++ b/examples/common/imgui/ocornut_imgui.cpp @@ -251,8 +251,16 @@ struct OcornutImguiContext ImGui::NewFrame(); - //ImGui::ShowTestWindow(); //Debug only. - // +#if 0 + ImGui::ShowTestWindow(); //Debug only. +#endif // 0 + +#if 0 + extern void ShowExampleAppCustomNodeGraph(bool* opened); + bool opened = true; + ShowExampleAppCustomNodeGraph(&opened); +#endif // 0 + #if defined(SCI_NAMESPACE) && 0 bool opened = true; ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) );