From a5af917f4b6aa2990551c925118ca73a2033ab7e Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 3 Mar 2024 20:22:06 +0100 Subject: [PATCH] Updated imgui-node-editor to commit 32dc92e --- 3rdparty/imgui-node-editor/crude_json.cpp | 15 +- 3rdparty/imgui-node-editor/crude_json.h | 15 +- 3rdparty/imgui-node-editor/docs/CHANGELOG.txt | 68 +- .../examples/application/CMakeLists.txt | 7 +- .../application/source/imgui_extra_keys.h | 17 + .../application/source/imgui_impl_opengl3.cpp | 701 ++++++++++++------ .../application/source/imgui_impl_opengl3.h | 69 +- .../application/source/imgui_impl_win32.cpp | 4 + .../application/source/renderer_ogl3.cpp | 5 +- .../blueprints-example/blueprints-example.cpp | 42 +- .../blueprints-example/utilities/builders.cpp | 12 +- .../blueprints-example/utilities/drawing.cpp | 2 +- .../blueprints-example/utilities/widgets.cpp | 2 +- .../canvas-example/canvas-example.cpp | 2 +- .../imgui-node-editor/imgui_bezier_math.inl | 36 +- 3rdparty/imgui-node-editor/imgui_canvas.cpp | 50 +- 3rdparty/imgui-node-editor/imgui_canvas.h | 45 +- 3rdparty/imgui-node-editor/imgui_extra_math.h | 6 +- .../imgui-node-editor/imgui_extra_math.inl | 4 + .../imgui-node-editor/imgui_node_editor.cpp | 163 ++-- .../imgui-node-editor/imgui_node_editor.h | 307 ++++---- .../imgui_node_editor_api.cpp | 12 - .../imgui_node_editor_internal.h | 20 +- 23 files changed, 1005 insertions(+), 599 deletions(-) diff --git a/3rdparty/imgui-node-editor/crude_json.cpp b/3rdparty/imgui-node-editor/crude_json.cpp index 38617e5..078427a 100644 --- a/3rdparty/imgui-node-editor/crude_json.cpp +++ b/3rdparty/imgui-node-editor/crude_json.cpp @@ -1,11 +1,3 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - // Crude implementation of JSON value object and parser. // // VERSION 0.1 @@ -569,7 +561,7 @@ private: if (end != hex.c_str() + hex.size()) return false; - c = v; + c = static_cast(v); return true; } @@ -896,8 +888,3 @@ bool value::save(const string& path, const int indent, const char indent_char) c # endif } // namespace crude_json - -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif diff --git a/3rdparty/imgui-node-editor/crude_json.h b/3rdparty/imgui-node-editor/crude_json.h index 48e7dff..f1eff29 100644 --- a/3rdparty/imgui-node-editor/crude_json.h +++ b/3rdparty/imgui-node-editor/crude_json.h @@ -1,10 +1,4 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#endif - -// Crude implementation of JSON value object and parser. +// Crude implementation of JSON value object and parser. // // VERSION 0.1 // @@ -253,9 +247,4 @@ template <> inline number* value::get_ptr() { if (m_Type = } // namespace crude_json -# endif // __CRUDE_JSON_H__ - -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif +# endif // __CRUDE_JSON_H__ \ No newline at end of file diff --git a/3rdparty/imgui-node-editor/docs/CHANGELOG.txt b/3rdparty/imgui-node-editor/docs/CHANGELOG.txt index 78da356..0e70996 100644 --- a/3rdparty/imgui-node-editor/docs/CHANGELOG.txt +++ b/3rdparty/imgui-node-editor/docs/CHANGELOG.txt @@ -1,4 +1,70 @@ -v0.9.1 (WIP): +v0.9.4 (WIP): + + NEW: Editor: Add smooth zoom (#266) + + BUGFIX: Canvas: Remember index of first command buffer to not miss updating any used (#260) + + BUGFIX: Editor: Don't duplicated ImVec2/ImVec3 == != operators defined since ImGui r19002 (#268) + + BUGFIX: Examples: Use imgui_impl_opengl3_loader.h instead of gl3w (#264) + +v0.9.3 (2023-10-14): + + CHANGE: Canvas: Use ImDrawCallback_ImCanvas macro as draw callback sentinel (#256), thanks @nspitko + + BUGFIX: Canvas: Ensure SentinelDrawCallback cleanup (#255) + + BUGFIX: Editor: Don't call Reasume/Suspend on invisible canvas (#255) + +v0.9.2 (2023-09-01): + + NEW: Editor: Add offset of hover/select to style (thanks @MultiPain) + + NEW: Editor: Add IMGUI_NODE_EDITOR_API to support building editor as a shared library (#189) + + NEW: Canvas: Add IMGUIEX_CANVAS_API to support building canvas as a shared library (#189) + + CHANGE: Editor: Support ImGui r18836 after SetItemUsingMouseWheel removal (#218), thanks @ocornut + + CHANGE: Editor: Define IMGUI_DEFINE_MATH_OPERATORS before (#209), thanks @ocornut + + CHANGE: Examples: Define IMGUI_DEFINE_MATH_OPERATORS before (#209), thanks @ocornut + + CHANGE: Canvas: Don't use deprecated SetItemAllowOverlap (#250) + + CHANGE: Examples: Don't use deprecated SetItemAllowOverlap (#250) + + CHANGE: Editor: Define IMGUI_DEFINE_MATH_OPERATORS before (#209), thanks @ocornut + + CHANGE: Editor: Unary operator- for ImVec2 is defined by ImGui since r18955 (#248) + + BUGFIX: Editor: Correctly initialize 'width' for view resize code (thx @gnif) + + BUGFIX: Examples: Handle node deletion before links (#182) + Deleting node queue connected links for deletion. + + BUGFIX: Examples: Simplify and fix drawing of node header line (#180) + + BUGFIX: Editor: Cleanup tabs. + + BUGFIX: Editor: Use ImGuiKey directly with ImGui r18822 (#183) + + BUGFIX: Examples: Use ImGuiKey directly with ImGui r18822 (#183) + + BUGFIX: Examples: Use ImGuiKey_KeypadEnter with ImGui r18604 (#183) + + BUGFIX: Examples: Add missing include for std::intptr_t (#199) + + BUGFIX: Examples: Don't use empty string as identifier + + BUGFIX: Editor: Clean long to int implicit cast warning in crude_json + + BUGFIX: Canvas: Ensure canvas draw commands are separated from other ImGui draw commands (#205, #250) + + BUGFIX: Editor: Don't call Canvas.End() when Canvas.Begin() failed (#186), thanks @pthom, @TheZoc + + +v0.9.1 (2022-08-27): CHANGE: Remove unwanted extra frame height from node bottom diff --git a/3rdparty/imgui-node-editor/examples/application/CMakeLists.txt b/3rdparty/imgui-node-editor/examples/application/CMakeLists.txt index ccd055b..7aa684b 100644 --- a/3rdparty/imgui-node-editor/examples/application/CMakeLists.txt +++ b/3rdparty/imgui-node-editor/examples/application/CMakeLists.txt @@ -69,15 +69,12 @@ endif() if (OpenGL_FOUND) set(HAVE_OPENGL YES) - find_package(gl3w REQUIRED) - # Explicitly select embedded GL3W loader - target_compile_definitions(application PRIVATE IMGUI_IMPL_OPENGL_LOADER_GL3W) - target_include_directories(application PRIVATE ${OPENGL_INCLUDE_DIR}) - target_link_libraries(application PRIVATE ${OPENGL_gl_LIBRARY} gl3w) + target_link_libraries(application PRIVATE ${OPENGL_gl_LIBRARY}) list(APPEND _Application_Sources source/imgui_impl_opengl3.cpp source/imgui_impl_opengl3.h + source/imgui_impl_opengl3_loader.h ) endif() diff --git a/3rdparty/imgui-node-editor/examples/application/source/imgui_extra_keys.h b/3rdparty/imgui-node-editor/examples/application/source/imgui_extra_keys.h index 850d51a..2135b40 100644 --- a/3rdparty/imgui-node-editor/examples/application/source/imgui_extra_keys.h +++ b/3rdparty/imgui-node-editor/examples/application/source/imgui_extra_keys.h @@ -1,5 +1,8 @@ # pragma once # include + +# if !defined(IMGUI_VERSION_NUM) || (IMGUI_VERSION_NUM < 18822) + # include // https://stackoverflow.com/a/8597498 @@ -46,3 +49,17 @@ static inline int GetEnumValueForD() { return KeyTester_ImGuiKey_D::Get(nullptr); } + +# else + +static inline ImGuiKey GetEnumValueForF() +{ + return ImGuiKey_F; +} + +static inline ImGuiKey GetEnumValueForD() +{ + return ImGuiKey_D; +} + +# endif \ No newline at end of file diff --git a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.cpp b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.cpp index 3e55698..08cc84a 100644 --- a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.cpp +++ b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.cpp @@ -1,18 +1,54 @@ -// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline +// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline // - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) -// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) +// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. +// [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui +// About WebGL/ES: +// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. +// - This is done automatically on iOS, Android and Emscripten targets. +// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. + +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accomodating for NetBSD systems having only "libGL.so.3" available. (#6983) +// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445) +// 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333) +// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375) +// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333) +// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224) +// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530) +// 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224) +// 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes). +// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. +// 2022-09-27: OpenGL: Added ability to '#define IMGUI_IMPL_OPENGL_DEBUG'. +// 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127). +// 2022-05-13: OpenGL: Fixed state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states. +// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers. +// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions. +// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader. +// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). +// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state. +// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader. +// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. +// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) +// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. +// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer. +// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. +// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. +// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) +// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. // 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX. // 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix. @@ -39,7 +75,7 @@ // 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. // 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state. -// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer. +// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a nullptr pointer. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. @@ -73,186 +109,332 @@ #endif #include "imgui.h" +#ifndef IMGUI_DISABLE #include "imgui_impl_opengl3.h" #include -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else #include // intptr_t +#if defined(__APPLE__) +#include #endif +// Clang/GCC warnings with -Weverything +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast +#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness +#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used +#pragma clang diagnostic ignored "-Wnonportable-system-include-path" +#pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) +#endif +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind +#pragma GCC diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' +#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) +#endif // GL includes #if defined(IMGUI_IMPL_OPENGL_ES2) -#include +#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) +#include // Use GL ES 2 +#else +#include // Use GL ES 2 +#endif +#if defined(__EMSCRIPTEN__) +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif +#include +#endif #elif defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) #include // Use GL ES 3 #else #include // Use GL ES 3 #endif -#else -// About Desktop OpenGL function loaders: -// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. -#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) -#include // Needs to be initialized with gl3wInit() in user's code -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) -#include // Needs to be initialized with glewInit() in user's code. -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) -#include // Needs to be initialized with gladLoadGL() in user's code. -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) -#include // Needs to be initialized with gladLoadGL(...) or gladLoaderLoadGL() in user's code. -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) -#ifndef GLFW_INCLUDE_NONE -#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors. +#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) +// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. +// Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w. +// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.). +// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp): +// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped +// - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases +// Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version. +#define IMGL3W_IMPL +#include "imgui_impl_opengl3_loader.h" #endif -#include // Needs to be initialized with glbinding::Binding::initialize() in user's code. -#include -using namespace gl; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) -#ifndef GLFW_INCLUDE_NONE -#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors. -#endif -#include // Needs to be initialized with glbinding::initialize() in user's code. -#include -using namespace gl; -#else -#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM + +// Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension +#ifndef IMGUI_IMPL_OPENGL_ES2 +#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY +#elif defined(__EMSCRIPTEN__) +#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY +#define glBindVertexArray glBindVertexArrayOES +#define glGenVertexArrays glGenVertexArraysOES +#define glDeleteVertexArrays glDeleteVertexArraysOES +#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #endif + +// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. +#ifdef GL_POLYGON_MODE +#define IMGUI_IMPL_HAS_POLYGON_MODE #endif // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. -#if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) || !defined(GL_VERSION_3_2) -#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 0 +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET +#endif + +// Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() +#if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER +#endif + +// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART +#endif + +// Desktop GL use extension detection +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS +#endif + +// [Debugging] +//#define IMGUI_IMPL_OPENGL_DEBUG +#ifdef IMGUI_IMPL_OPENGL_DEBUG +#include +#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check #else -#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 1 +#define GL_CALL(_CALL) _CALL // Call without error check #endif // OpenGL Data -static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) -static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings. -static GLuint g_FontTexture = 0; -static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location -static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location -static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; +struct ImGui_ImplOpenGL3_Data +{ + GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) + char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings. + bool GlProfileIsES2; + bool GlProfileIsES3; + bool GlProfileIsCompat; + GLint GlProfileMask; + GLuint FontTexture; + GLuint ShaderHandle; + GLint AttribLocationTex; // Uniforms location + GLint AttribLocationProjMtx; + GLuint AttribLocationVtxPos; // Vertex attributes location + GLuint AttribLocationVtxUV; + GLuint AttribLocationVtxColor; + unsigned int VboHandle, ElementsHandle; + GLsizeiptr VertexBufferSize; + GLsizeiptr IndexBufferSize; + bool HasClipOrigin; + bool UseBufferSubData; + + ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } +}; + +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; +} + +// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only) +#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY +struct ImGui_ImplOpenGL3_VtxAttribState +{ + GLint Enabled, Size, Type, Normalized, Stride; + GLvoid* Ptr; + + void GetState(GLint index) + { + glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled); + glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size); + glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type); + glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized); + glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride); + glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr); + } + void SetState(GLint index) + { + glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr); + if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index); + } +}; +#endif // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { - // Query for GL version (e.g. 320 for GL 3.2) -#if !defined(IMGUI_IMPL_OPENGL_ES2) - GLint major, minor; - glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - g_GlVersion = (GLuint)(major * 100 + minor * 10); -#else - g_GlVersion = 200; // GLES 2 + ImGuiIO& io = ImGui::GetIO(); + IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); + + // Initialize our loader +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) + if (imgl3wInit() != 0) + { + fprintf(stderr, "Failed to initialize OpenGL loader!\n"); + return false; + } #endif - // Setup back-end capabilities flags - ImGuiIO& io = ImGui::GetIO(); + // Setup backend capabilities flags + ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)(); + io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_opengl3"; -#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET - if (g_GlVersion >= 320) + + // Query for GL version (e.g. 320 for GL 3.2) +#if defined(IMGUI_IMPL_OPENGL_ES2) + // GLES 2 + bd->GlVersion = 200; + bd->GlProfileIsES2 = true; +#else + // Desktop or GLES 3 + GLint major = 0; + GLint minor = 0; + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); + if (major == 0 && minor == 0) + { + // Query GL_VERSION in desktop GL 2.x, the string will start with "." + const char* gl_version = (const char*)glGetString(GL_VERSION); + sscanf(gl_version, "%d.%d", &major, &minor); + } + bd->GlVersion = (GLuint)(major * 100 + minor * 10); +#if defined(GL_CONTEXT_PROFILE_MASK) + if (bd->GlVersion >= 320) + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask); + bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; +#endif + +#if defined(IMGUI_IMPL_OPENGL_ES3) + bd->GlProfileIsES3 = true; +#endif + + bd->UseBufferSubData = false; + /* + // Query vendor to enable glBufferSubData kludge +#ifdef _WIN32 + if (const char* vendor = (const char*)glGetString(GL_VENDOR)) + if (strncmp(vendor, "Intel", 5) == 0) + bd->UseBufferSubData = true; +#endif + */ +#endif + +#ifdef IMGUI_IMPL_OPENGL_DEBUG + printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] +#endif + +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET + if (bd->GlVersion >= 320) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. #endif // Store GLSL version string so we can refer to it later in case we recreate shaders. - // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. + // Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure. + if (glsl_version == nullptr) + { #if defined(IMGUI_IMPL_OPENGL_ES2) - if (glsl_version == NULL) glsl_version = "#version 100"; #elif defined(IMGUI_IMPL_OPENGL_ES3) - if (glsl_version == NULL) glsl_version = "#version 300 es"; #elif defined(__APPLE__) - if (glsl_version == NULL) glsl_version = "#version 150"; #else - if (glsl_version == NULL) glsl_version = "#version 130"; #endif - IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); - strcpy(g_GlslVersionString, glsl_version); - strcat(g_GlslVersionString, "\n"); - - // Debugging construct to make it easily visible in the IDE and debugger which GL loader has been selected. - // The code actually never uses the 'gl_loader' variable! It is only here so you can read it! - // If auto-detection fails or doesn't select the same GL loader file as used by your application, - // you are likely to get a crash below. - // You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. - const char* gl_loader = "Unknown"; - IM_UNUSED(gl_loader); -#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) - gl_loader = "GL3W"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) - gl_loader = "GLEW"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) - gl_loader = "GLAD"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) - gl_loader = "GLAD2"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) - gl_loader = "glbinding2"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) - gl_loader = "glbinding3"; -#elif defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) - gl_loader = "custom"; -#else - gl_loader = "none"; -#endif + } + IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString)); + strcpy(bd->GlslVersionString, glsl_version); + strcat(bd->GlslVersionString, "\n"); // Make an arbitrary GL call (we don't actually need the result) - // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. - // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. + // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know! GLint current_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); + // Detect extensions we support + bd->HasClipOrigin = (bd->GlVersion >= 450); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS + GLint num_extensions = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); + for (GLint i = 0; i < num_extensions; i++) + { + const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); + if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0) + bd->HasClipOrigin = true; + } +#endif + return true; } void ImGui_ImplOpenGL3_Shutdown() { + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOpenGL3_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; + io.BackendRendererUserData = nullptr; + io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; + IM_DELETE(bd); } void ImGui_ImplOpenGL3_NewFrame() { - if (!g_ShaderHandle) + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?"); + + if (!bd->ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) { + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + if (bd->GlVersion >= 310) + glDisable(GL_PRIMITIVE_RESTART); +#endif +#ifdef IMGUI_IMPL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) +#if defined(GL_CLIP_ORIGIN) bool clip_origin_lower_left = true; -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) - GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); - if (current_clip_origin == GL_UPPER_LEFT) - clip_origin_lower_left = false; + if (bd->HasClipOrigin) + { + GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); + if (current_clip_origin == GL_UPPER_LEFT) + clip_origin_lower_left = false; + } #endif // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); + GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height)); float L = draw_data->DisplayPos.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; +#if defined(GL_CLIP_ORIGIN) if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left +#endif const float ortho_projection[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, @@ -260,32 +442,34 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid { 0.0f, 0.0f, -1.0f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. + glUseProgram(bd->ShaderHandle); + glUniform1i(bd->AttribLocationTex, 0); + glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER + if (bd->GlVersion >= 330 || bd->GlProfileIsES3) + glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise. #endif (void)vertex_array_object; -#ifndef IMGUI_IMPL_OPENGL_ES2 +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(vertex_array_object); #endif // Bind vertex/index buffers and setup attributes for ImDrawVert - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); - glEnableVertexAttribArray(g_AttribLocationVtxPos); - glEnableVertexAttribArray(g_AttribLocationVtxUV); - glEnableVertexAttribArray(g_AttribLocationVtxColor); - glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle)); + GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos)); + GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV)); + GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor)); + GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos))); + GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv))); + GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col))); } // OpenGL3 Render function. -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly. +// This is in order to be able to run within an OpenGL engine that doesn't do so. void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) @@ -294,19 +478,28 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (fb_width <= 0 || fb_height <= 0) return; + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + // Backup GL state GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); glActiveTexture(GL_TEXTURE0); GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); -#ifdef GL_SAMPLER_BINDING - GLuint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER + GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } #endif GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 +#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY + // This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+. + GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); + ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos); + ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV); + ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor); +#endif +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); #endif -#ifdef GL_POLYGON_MODE +#ifdef IMGUI_IMPL_HAS_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); #endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); @@ -320,14 +513,18 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); + GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; +#endif // Setup desired GL state // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. GLuint vertex_array_object = 0; -#ifndef IMGUI_IMPL_OPENGL_ES2 - glGenVertexArrays(1, &vertex_array_object); +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY + GL_CALL(glGenVertexArrays(1, &vertex_array_object)); #endif ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); @@ -341,13 +538,40 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) const ImDrawList* cmd_list = draw_data->CmdLists[n]; // Upload vertex/index buffers - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); + // - OpenGL drivers are in a very sorry state nowadays.... + // During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports + // of leaks on Intel GPU when using multi-viewports on Windows. + // - After this we kept hearing of various display corruptions issues. We started disabling on non-Intel GPU, but issues still got reported on Intel. + // - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code. + // We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path. + // - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues. + const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); + const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); + if (bd->UseBufferSubData) + { + if (bd->VertexBufferSize < vtx_buffer_size) + { + bd->VertexBufferSize = vtx_buffer_size; + GL_CALL(glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, nullptr, GL_STREAM_DRAW)); + } + if (bd->IndexBufferSize < idx_buffer_size) + { + bd->IndexBufferSize = idx_buffer_size; + GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW)); + } + GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data)); + GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data)); + } + else + { + GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW)); + GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW)); + } for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback != NULL) + if (pcmd->UserCallback != nullptr) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) @@ -359,112 +583,137 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) else { // Project scissor/clipping rectangles into framebuffer space - ImVec4 clip_rect; - clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; - clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; - clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; - clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; + ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); + ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); + if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) + continue; - if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) - { - // Apply scissor/clipping rectangle - glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); + // Apply scissor/clipping rectangle (Y is inverted in OpenGL) + GL_CALL(glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); - // Bind texture, Draw - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); -#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET - if (g_GlVersion >= 320) - glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); - else + // Bind texture, Draw + GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET + if (bd->GlVersion >= 320) + GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset)); + else #endif - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); - } + GL_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); } } } // Destroy the temporary VAO -#ifndef IMGUI_IMPL_OPENGL_ES2 - glDeleteVertexArrays(1, &vertex_array_object); +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY + GL_CALL(glDeleteVertexArrays(1, &vertex_array_object)); #endif // Restore modified GL state - glUseProgram(last_program); + // This "glIsProgram()" check is required because if the program is "pending deletion" at the time of binding backup, it will have been deleted by now and will cause an OpenGL error. See #6220. + if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, last_sampler); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER + if (bd->GlVersion >= 330 || bd->GlProfileIsES3) + glBindSampler(0, last_sampler); #endif glActiveTexture(last_active_texture); -#ifndef IMGUI_IMPL_OPENGL_ES2 +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array_object); #endif glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); +#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); + last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos); + last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV); + last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor); +#endif glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif + +#ifdef IMGUI_IMPL_HAS_POLYGON_MODE + // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons + if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) + { + glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); + glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); + } + else + { + glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); + } +#endif // IMGUI_IMPL_HAS_POLYGON_MODE + glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); + (void)bd; // Not all compilation paths use this } bool ImGui_ImplOpenGL3_CreateFontsTexture() { - // Build texture atlas ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + + // Build texture atlas unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. // Upload texture to graphics system + // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef GL_UNPACK_ROW_LENGTH - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); + GL_CALL(glGenTextures(1, &bd->FontTexture)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); +#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES + GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); #endif - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); // Store our identifier - io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture; + io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); + GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); return true; } void ImGui_ImplOpenGL3_DestroyFontsTexture() { - if (g_FontTexture) + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + if (bd->FontTexture) { - ImGuiIO& io = ImGui::GetIO(); - glDeleteTextures(1, &g_FontTexture); - io.Fonts->TexID = 0; - g_FontTexture = 0; + glDeleteTextures(1, &bd->FontTexture); + io.Fonts->SetTexID(0); + bd->FontTexture = 0; } } // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. static bool CheckShader(GLuint handle, const char* desc) { + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetShaderiv(handle, GL_COMPILE_STATUS, &status); glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE) - fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); + fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector buf; buf.resize((int)(log_length + 1)); - glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); + glGetShaderInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } return (GLboolean)status == GL_TRUE; @@ -473,16 +722,17 @@ static bool CheckShader(GLuint handle, const char* desc) // If you get an error please report on GitHub. You may try different GL context version or GLSL version. static bool CheckProgram(GLuint handle, const char* desc) { + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetProgramiv(handle, GL_LINK_STATUS, &status); glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE) - fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString); + fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector buf; buf.resize((int)(log_length + 1)); - glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); + glGetProgramInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } return (GLboolean)status == GL_TRUE; @@ -490,18 +740,20 @@ static bool CheckProgram(GLuint handle, const char* desc) bool ImGui_ImplOpenGL3_CreateDeviceObjects() { + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + // Backup GL state GLint last_texture, last_array_buffer; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); #endif // Parse GLSL version string int glsl_version = 130; - sscanf(g_GlslVersionString, "#version %d", &glsl_version); + sscanf(bd->GlslVersionString, "#version %d", &glsl_version); const GLchar* vertex_shader_glsl_120 = "uniform mat4 ProjMtx;\n" @@ -532,7 +784,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() "}\n"; const GLchar* vertex_shader_glsl_300_es = - "precision mediump float;\n" + "precision highp float;\n" "layout (location = 0) in vec2 Position;\n" "layout (location = 1) in vec2 UV;\n" "layout (location = 2) in vec4 Color;\n" @@ -569,9 +821,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() "varying vec4 Frag_Color;\n" "void main()\n" "{\n" - " vec4 col = Frag_Color * texture2D(Texture, Frag_UV.st);\n" - " col.xyz *= col.w;" - " gl_FragColor = col;\n" + " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_130 = @@ -581,9 +831,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() "out vec4 Out_Color;\n" "void main()\n" "{\n" - " vec4 col = Frag_Color * texture2D(Texture, Frag_UV.st);\n" - " col.xyz *= col.w;" - " gl_FragColor = col;\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_300_es = @@ -594,9 +842,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" - " vec4 col = Frag_Color * texture2D(Texture, Frag_UV.st);\n" - " col.xyz *= col.w;" - " gl_FragColor = col;\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_410_core = @@ -606,14 +852,12 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" - " vec4 col = Frag_Color * texture2D(Texture, Frag_UV.st);\n" - " col.xyz *= col.w;" - " gl_FragColor = col;\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; // Select shaders matching our GLSL versions - const GLchar* vertex_shader = NULL; - const GLchar* fragment_shader = NULL; + const GLchar* vertex_shader = nullptr; + const GLchar* fragment_shader = nullptr; if (glsl_version < 130) { vertex_shader = vertex_shader_glsl_120; @@ -636,40 +880,46 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() } // Create shaders - const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader }; - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); - glCompileShader(g_VertHandle); - CheckShader(g_VertHandle, "vertex shader"); + const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader }; + GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr); + glCompileShader(vert_handle); + CheckShader(vert_handle, "vertex shader"); - const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader }; - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); - glCompileShader(g_FragHandle); - CheckShader(g_FragHandle, "fragment shader"); + const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader }; + GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr); + glCompileShader(frag_handle); + CheckShader(frag_handle, "fragment shader"); - g_ShaderHandle = glCreateProgram(); - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - CheckProgram(g_ShaderHandle, "shader program"); + // Link + bd->ShaderHandle = glCreateProgram(); + glAttachShader(bd->ShaderHandle, vert_handle); + glAttachShader(bd->ShaderHandle, frag_handle); + glLinkProgram(bd->ShaderHandle); + CheckProgram(bd->ShaderHandle, "shader program"); - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationVtxPos = (GLuint)glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationVtxUV = (GLuint)glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationVtxColor = (GLuint)glGetAttribLocation(g_ShaderHandle, "Color"); + glDetachShader(bd->ShaderHandle, vert_handle); + glDetachShader(bd->ShaderHandle, frag_handle); + glDeleteShader(vert_handle); + glDeleteShader(frag_handle); + + bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture"); + bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx"); + bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position"); + bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV"); + bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color"); // Create buffers - glGenBuffers(1, &g_VboHandle); - glGenBuffers(1, &g_ElementsHandle); + glGenBuffers(1, &bd->VboHandle); + glGenBuffers(1, &bd->ElementsHandle); ImGui_ImplOpenGL3_CreateFontsTexture(); // Restore modified GL state glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 +#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array); #endif @@ -678,13 +928,20 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() void ImGui_ImplOpenGL3_DestroyDeviceObjects() { - if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; } - if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; } - if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); } - if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); } - if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; } - if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; } - if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; } - + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; } + if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; } + if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } ImGui_ImplOpenGL3_DestroyFontsTexture(); } + +//----------------------------------------------------------------------------- + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.h b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.h index 14eb284..23eb924 100644 --- a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.h +++ b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_opengl3.h @@ -1,31 +1,36 @@ -// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline +// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline // - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) -// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) +// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. +// [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui +// About WebGL/ES: +// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. +// - This is done automatically on iOS, Android and Emscripten targets. +// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. -// About Desktop OpenGL function loaders: -// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. -// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). -// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp // About GLSL version: -// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. +// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. #pragma once #include "imgui.h" // IMGUI_IMPL_API +#ifndef IMGUI_DISABLE // Backend API -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); @@ -40,48 +45,22 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android -// Attempt to auto-detect the default Desktop GL loader based on available header files. -// If auto-detection fails or doesn't select the same GL loader file as used by your application, -// you are likely to get a crash in ImGui_ImplOpenGL3_Init(). -// You can explicitly select a loader by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. +// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. #if !defined(IMGUI_IMPL_OPENGL_ES2) \ - && !defined(IMGUI_IMPL_OPENGL_ES3) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) \ - && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) + && !defined(IMGUI_IMPL_OPENGL_ES3) // Try to detect GLES on matching platforms #if defined(__APPLE__) -#include "TargetConditionals.h" +#include #endif #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" -#elif defined(__EMSCRIPTEN__) +#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" - -// Otherwise try to detect supported Desktop OpenGL loaders.. -#elif defined(__has_include) -#if __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GLEW -#elif __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GLAD -#elif __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GLAD2 -#elif __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GL3W -#elif __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GLBINDING3 -#elif __has_include() - #define IMGUI_IMPL_OPENGL_LOADER_GLBINDING2 #else - #error "Cannot detect OpenGL loader!" -#endif -#else - #define IMGUI_IMPL_OPENGL_LOADER_GL3W // Default to GL3W embedded in our repository +// Otherwise imgui_impl_opengl3_loader.h will be used. #endif #endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_win32.cpp b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_win32.cpp index 6f158de..f6ccb3e 100644 --- a/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_win32.cpp +++ b/3rdparty/imgui-node-editor/examples/application/source/imgui_impl_win32.cpp @@ -93,7 +93,11 @@ bool ImGui_ImplWin32_Init(void* hwnd) io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; +# if defined(IMGUI_VERSION_NUM) && (IMGUI_VERSION_NUM >= 18604) + io.KeyMap[ImGuiKey_KeypadEnter] = VK_RETURN; +# else io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; +# endif io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; io.KeyMap[ImGuiKey_V] = 'V'; diff --git a/3rdparty/imgui-node-editor/examples/application/source/renderer_ogl3.cpp b/3rdparty/imgui-node-editor/examples/application/source/renderer_ogl3.cpp index 72a7dfc..8ea98d8 100644 --- a/3rdparty/imgui-node-editor/examples/application/source/renderer_ogl3.cpp +++ b/3rdparty/imgui-node-editor/examples/application/source/renderer_ogl3.cpp @@ -4,6 +4,7 @@ # include "platform.h" # include +# include // std::intptr_t # if PLATFORM(WINDOWS) # define NOMINMAX @@ -31,8 +32,10 @@ using namespace gl; # include // Initialize with glbinding::initialize() # include using namespace gl; -# else +# elif defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) # include IMGUI_IMPL_OPENGL_LOADER_CUSTOM +# else +# include "imgui_impl_opengl3_loader.h" # endif struct ImTexture diff --git a/3rdparty/imgui-node-editor/examples/blueprints-example/blueprints-example.cpp b/3rdparty/imgui-node-editor/examples/blueprints-example/blueprints-example.cpp index c14c2e3..f72f3ad 100644 --- a/3rdparty/imgui-node-editor/examples/blueprints-example/blueprints-example.cpp +++ b/3rdparty/imgui-node-editor/examples/blueprints-example/blueprints-example.cpp @@ -1,10 +1,9 @@ +#define IMGUI_DEFINE_MATH_OPERATORS #include #include "utilities/builders.h" #include "utilities/widgets.h" #include - -#define IMGUI_DEFINE_MATH_OPERATORS #include #include @@ -648,7 +647,9 @@ struct Example: ImGui::DragFloat("Node Rounding", &editorStyle.NodeRounding, 0.1f, 0.0f, 40.0f); ImGui::DragFloat("Node Border Width", &editorStyle.NodeBorderWidth, 0.1f, 0.0f, 15.0f); ImGui::DragFloat("Hovered Node Border Width", &editorStyle.HoveredNodeBorderWidth, 0.1f, 0.0f, 15.0f); + ImGui::DragFloat("Hovered Node Border Offset", &editorStyle.HoverNodeBorderOffset, 0.1f, -40.0f, 40.0f); ImGui::DragFloat("Selected Node Border Width", &editorStyle.SelectedNodeBorderWidth, 0.1f, 0.0f, 15.0f); + ImGui::DragFloat("Selected Node Border Offset", &editorStyle.SelectedNodeBorderOffset, 0.1f, -40.0f, 40.0f); ImGui::DragFloat("Pin Rounding", &editorStyle.PinRounding, 0.1f, 0.0f, 40.0f); ImGui::DragFloat("Pin Border Width", &editorStyle.PinBorderWidth, 0.1f, 0.0f, 15.0f); ImGui::DragFloat("Link Strength", &editorStyle.LinkStrength, 1.0f, 0.0f, 500.0f); @@ -682,7 +683,7 @@ struct Example: ImGui::EndHorizontal(); static ImGuiTextFilter filter; - filter.Draw("", paneWidth); + filter.Draw("##filter", paneWidth); ImGui::Spacing(); @@ -765,6 +766,9 @@ struct Example: } bool isSelected = std::find(selectedNodes.begin(), selectedNodes.end(), node.ID) != selectedNodes.end(); +# if IMGUI_VERSION_NUM >= 18967 + ImGui::SetNextItemAllowOverlap(); +# endif if (ImGui::Selectable((node.Name + "##" + std::to_string(reinterpret_cast(node.ID.AsPointer()))).c_str(), &isSelected)) { if (io.KeyCtrl) @@ -793,7 +797,11 @@ struct Example: auto drawList = ImGui::GetWindowDrawList(); ImGui::SetCursorScreenPos(iconPanelPos); +# if IMGUI_VERSION_NUM < 18967 ImGui::SetItemAllowOverlap(); +# else + ImGui::SetNextItemAllowOverlap(); +# endif if (node.SavedState.empty()) { if (ImGui::InvisibleButton("save", ImVec2((float)saveIconWidth, (float)saveIconHeight))) @@ -813,7 +821,11 @@ struct Example: } ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); +# if IMGUI_VERSION_NUM < 18967 ImGui::SetItemAllowOverlap(); +# else + ImGui::SetNextItemAllowOverlap(); +# endif if (!node.SavedState.empty()) { if (ImGui::InvisibleButton("restore", ImVec2((float)restoreIconWidth, (float)restoreIconHeight))) @@ -837,7 +849,9 @@ struct Example: } ImGui::SameLine(0, 0); +# if IMGUI_VERSION_NUM < 18967 ImGui::SetItemAllowOverlap(); +# endif ImGui::Dummy(ImVec2(0, (float)restoreIconHeight)); ImGui::PopID(); @@ -1537,17 +1551,6 @@ struct Example: if (ed::BeginDelete()) { - ed::LinkId linkId = 0; - while (ed::QueryDeletedLink(&linkId)) - { - if (ed::AcceptDeletedItem()) - { - auto id = std::find_if(m_Links.begin(), m_Links.end(), [linkId](auto& link) { return link.ID == linkId; }); - if (id != m_Links.end()) - m_Links.erase(id); - } - } - ed::NodeId nodeId = 0; while (ed::QueryDeletedNode(&nodeId)) { @@ -1558,6 +1561,17 @@ struct Example: m_Nodes.erase(id); } } + + ed::LinkId linkId = 0; + while (ed::QueryDeletedLink(&linkId)) + { + if (ed::AcceptDeletedItem()) + { + auto id = std::find_if(m_Links.begin(), m_Links.end(), [linkId](auto& link) { return link.ID == linkId; }); + if (id != m_Links.end()) + m_Links.erase(id); + } + } } ed::EndDelete(); } diff --git a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/builders.cpp b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/builders.cpp index dd6abf6..e8ae020 100644 --- a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/builders.cpp +++ b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/builders.cpp @@ -7,8 +7,8 @@ // CREDITS // Written by Michal Cichon //------------------------------------------------------------------------------ -# include "builders.h" # define IMGUI_DEFINE_MATH_OPERATORS +# include "builders.h" # include @@ -72,15 +72,11 @@ void util::BlueprintNodeBuilder::End() headerColor, GetStyle().NodeRounding, 1 | 2); #endif - - auto headerSeparatorMin = ImVec2(HeaderMin.x, HeaderMax.y); - auto headerSeparatorMax = ImVec2(HeaderMax.x, HeaderMin.y); - - if ((headerSeparatorMax.x > headerSeparatorMin.x) && (headerSeparatorMax.y > headerSeparatorMin.y)) + if (ContentMin.y > HeaderMax.y) { drawList->AddLine( - headerSeparatorMin + ImVec2(-(8 - halfBorderWidth), -0.5f), - headerSeparatorMax + ImVec2( (8 - halfBorderWidth), -0.5f), + ImVec2(HeaderMin.x - (8 - halfBorderWidth), HeaderMax.y - 0.5f), + ImVec2(HeaderMax.x + (8 - halfBorderWidth), HeaderMax.y - 0.5f), ImColor(255, 255, 255, 96 * alpha / (3 * 255)), 1.0f); } } diff --git a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/drawing.cpp b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/drawing.cpp index 208c9ce..1f255ee 100644 --- a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/drawing.cpp +++ b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/drawing.cpp @@ -1,5 +1,5 @@ -# include "drawing.h" # define IMGUI_DEFINE_MATH_OPERATORS +# include "drawing.h" # include void ax::Drawing::DrawIcon(ImDrawList* drawList, const ImVec2& a, const ImVec2& b, IconType type, bool filled, ImU32 color, ImU32 innerColor) diff --git a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/widgets.cpp b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/widgets.cpp index 9faa5e0..202c8e2 100644 --- a/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/widgets.cpp +++ b/3rdparty/imgui-node-editor/examples/blueprints-example/utilities/widgets.cpp @@ -1,5 +1,5 @@ -# include "widgets.h" # define IMGUI_DEFINE_MATH_OPERATORS +# include "widgets.h" # include void ax::Widgets::Icon(const ImVec2& size, IconType type, bool filled, const ImVec4& color/* = ImVec4(1, 1, 1, 1)*/, const ImVec4& innerColor/* = ImVec4(0, 0, 0, 0)*/) diff --git a/3rdparty/imgui-node-editor/examples/canvas-example/canvas-example.cpp b/3rdparty/imgui-node-editor/examples/canvas-example/canvas-example.cpp index 370f97b..f07c3e3 100644 --- a/3rdparty/imgui-node-editor/examples/canvas-example/canvas-example.cpp +++ b/3rdparty/imgui-node-editor/examples/canvas-example/canvas-example.cpp @@ -1,5 +1,5 @@ -# include # define IMGUI_DEFINE_MATH_OPERATORS +# include # include # include # include diff --git a/3rdparty/imgui-node-editor/imgui_bezier_math.inl b/3rdparty/imgui-node-editor/imgui_bezier_math.inl index 9f497f6..3020bdb 100644 --- a/3rdparty/imgui-node-editor/imgui_bezier_math.inl +++ b/3rdparty/imgui-node-editor/imgui_bezier_math.inl @@ -1,11 +1,3 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - //------------------------------------------------------------------------------ // VERSION 0.1 // @@ -403,19 +395,17 @@ inline ImCubicBezierIntersectResult ImCubicBezierLineIntersect(const ImVec2& p0, return count; }; - /* - https://github.com/kaishiqi/Geometric-Bezier/blob/master/GeometricBezier/src/kaishiqi/geometric/intersection/Intersection.as - - Start with Bezier using Bernstein polynomials for weighting functions: - (1-t^3)P0 + 3t(1-t)^2P1 + 3t^2(1-t)P2 + t^3P3 - - Expand and collect terms to form linear combinations of original Bezier - controls. This ends up with a vector cubic in t: - (-P0+3P1-3P2+P3)t^3 + (3P0-6P1+3P2)t^2 + (-3P0+3P1)t + P0 - /\ /\ /\ /\ - || || || || - c3 c2 c1 c0 - */ + // https://github.com/kaishiqi/Geometric-Bezier/blob/master/GeometricBezier/src/kaishiqi/geometric/intersection/Intersection.as + // + // Start with Bezier using Bernstein polynomials for weighting functions: + // (1-t^3)P0 + 3t(1-t)^2P1 + 3t^2(1-t)P2 + t^3P3 + // + // Expand and collect terms to form linear combinations of original Bezier + // controls. This ends up with a vector cubic in t: + // (-P0+3P1-3P2+P3)t^3 + (3P0-6P1+3P2)t^2 + (-3P0+3P1)t + P0 + // /\ /\ /\ /\ + // || || || || + // c3 c2 c1 c0 // Calculate the coefficients auto c3 = -p0 + 3 * p1 - 3 * p2 + p3; @@ -683,7 +673,3 @@ inline void ImCubicBezierFixedStep(F& callback, const ImCubicBezierPoints& curve //------------------------------------------------------------------------------ # endif // __IMGUI_BEZIER_MATH_INL__ - -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif diff --git a/3rdparty/imgui-node-editor/imgui_canvas.cpp b/3rdparty/imgui-node-editor/imgui_canvas.cpp index c58c8ed..2010ee3 100644 --- a/3rdparty/imgui-node-editor/imgui_canvas.cpp +++ b/3rdparty/imgui-node-editor/imgui_canvas.cpp @@ -1,4 +1,6 @@ -# define IMGUI_DEFINE_MATH_OPERATORS +# ifndef IMGUI_DEFINE_MATH_OPERATORS +# define IMGUI_DEFINE_MATH_OPERATORS +# endif # include "imgui_canvas.h" # include @@ -25,6 +27,11 @@ static constexpr bool value = (sizeof(yes_type) == sizeof(test(0))); \ } +// Special sentinel value. This needs to be unique, so allow it to be overridden in the user's ImGui config +# ifndef ImDrawCallback_ImCanvas +# define ImDrawCallback_ImCanvas (ImDrawCallback)(-2) +# endif + namespace ImCanvasDetails { DECLARE_HAS_MEMBER(HasFringeScale, _FringeScale); @@ -115,7 +122,7 @@ bool ImGuiEx::Canvas::Begin(ImGuiID id, const ImVec2& size) // #debug: Canvas content. //m_DrawList->AddRectFilled(m_StartPos, m_StartPos + m_CurrentSize, IM_COL32(0, 0, 0, 64)); - m_DrawList->AddRect(m_WidgetRect.Min, m_WidgetRect.Max, IM_COL32(255, 0, 255, 64)); + //m_DrawList->AddRect(m_WidgetRect.Min, m_WidgetRect.Max, IM_COL32(255, 0, 255, 64)); ImGui::SetCursorScreenPos(ImVec2(0.0f, 0.0f)); @@ -131,6 +138,10 @@ bool ImGuiEx::Canvas::Begin(ImGuiID id, const ImVec2& size) EnterLocalSpace(); +# if IMGUI_VERSION_NUM >= 18967 + ImGui::SetNextItemAllowOverlap(); +# endif + // Emit dummy widget matching bounds of the canvas. ImGui::SetCursorScreenPos(m_ViewRect.Min); ImGui::Dummy(m_ViewRect.GetSize()); @@ -162,7 +173,9 @@ void ImGuiEx::Canvas::End() ImGui::GetCurrentWindow()->DC.CursorMaxPos = m_WindowCursorMaxBackup; +# if IMGUI_VERSION_NUM < 18967 ImGui::SetItemAllowOverlap(); +# endif // Emit dummy widget matching bounds of the canvas. ImGui::SetCursorScreenPos(m_WidgetPosition); @@ -407,6 +420,15 @@ void ImGuiEx::Canvas::EnterLocalSpace() auto clipped_clip_rect = m_DrawList->_ClipRectStack.back(); ImGui::PopClipRect(); +# if IMGUI_EX_CANVAS_DEFERED() + m_Ranges.resize(m_Ranges.Size + 1); + m_CurrentRange = &m_Ranges.back(); + m_CurrentRange->BeginComandIndex = ImMax(m_DrawList->CmdBuffer.Size, 0); + m_CurrentRange->BeginVertexIndex = m_DrawList->_VtxCurrentIdx + ImVtxOffsetRef(m_DrawList); +# endif + m_DrawListCommadBufferSize = ImMax(m_DrawList->CmdBuffer.Size, 0); + m_DrawListStartVertexIndex = m_DrawList->_VtxCurrentIdx + ImVtxOffsetRef(m_DrawList); + // Make sure we do not share draw command with anyone. We don't want to mess // with someones clip rectangle. @@ -421,16 +443,9 @@ void ImGuiEx::Canvas::EnterLocalSpace() // // More investigation is needed. To get to the bottom of this. if ((!m_DrawList->CmdBuffer.empty() && m_DrawList->CmdBuffer.back().ElemCount > 0) || m_DrawList->_Splitter._Count > 1) - m_DrawList->AddDrawCmd(); + m_DrawList->AddCallback(ImDrawCallback_ImCanvas, nullptr); -# if IMGUI_EX_CANVAS_DEFERED() - m_Ranges.resize(m_Ranges.Size + 1); - m_CurrentRange = &m_Ranges.back(); - m_CurrentRange->BeginComandIndex = ImMax(m_DrawList->CmdBuffer.Size - 1, 0); - m_CurrentRange->BeginVertexIndex = m_DrawList->_VtxCurrentIdx + ImVtxOffsetRef(m_DrawList); -# endif - m_DrawListCommadBufferSize = ImMax(m_DrawList->CmdBuffer.Size - 1, 0); - m_DrawListStartVertexIndex = m_DrawList->_VtxCurrentIdx + ImVtxOffsetRef(m_DrawList); + m_DrawListFirstCommandIndex = ImMax(m_DrawList->CmdBuffer.Size - 1, 0); # if defined(IMGUI_HAS_VIEWPORT) auto window = ImGui::GetCurrentWindow(); @@ -510,7 +525,7 @@ void ImGuiEx::Canvas::LeaveLocalSpace() } // Move clip rectangles to screen space. - for (int i = m_DrawListCommadBufferSize; i < m_DrawList->CmdBuffer.size(); ++i) + for (int i = m_DrawListFirstCommandIndex; i < m_DrawList->CmdBuffer.size(); ++i) { auto& command = m_DrawList->CmdBuffer[i]; command.ClipRect.x = command.ClipRect.x * m_View.Scale + m_ViewTransformPosition.x; @@ -529,7 +544,7 @@ void ImGuiEx::Canvas::LeaveLocalSpace() } // Move clip rectangles to screen space. - for (int i = m_DrawListCommadBufferSize; i < m_DrawList->CmdBuffer.size(); ++i) + for (int i = m_DrawListFirstCommandIndex; i < m_DrawList->CmdBuffer.size(); ++i) { auto& command = m_DrawList->CmdBuffer[i]; command.ClipRect.x = command.ClipRect.x + m_ViewTransformPosition.x; @@ -539,6 +554,15 @@ void ImGuiEx::Canvas::LeaveLocalSpace() } } + // Remove sentinel draw command if present + if (m_DrawListCommadBufferSize > 0) + { + if (m_DrawList->CmdBuffer.size() > m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize].UserCallback == ImDrawCallback_ImCanvas) + m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize); + else if (m_DrawList->CmdBuffer.size() >= m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize - 1].UserCallback == ImDrawCallback_ImCanvas) + m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize - 1); + } + auto& fringeScale = ImFringeScaleRef(m_DrawList); fringeScale = m_LastFringeScale; diff --git a/3rdparty/imgui-node-editor/imgui_canvas.h b/3rdparty/imgui-node-editor/imgui_canvas.h index e5e4959..de2a6f5 100644 --- a/3rdparty/imgui-node-editor/imgui_canvas.h +++ b/3rdparty/imgui-node-editor/imgui_canvas.h @@ -51,6 +51,10 @@ # include # include // ImRect, ImFloor +#ifndef IMGUIEX_CANVAS_API +#define IMGUIEX_CANVAS_API +#endif + namespace ImGuiEx { struct CanvasView @@ -106,13 +110,13 @@ struct Canvas // // You can query size of the canvas while it is being drawn // by calling Rect(). - bool Begin(const char* id, const ImVec2& size); - bool Begin(ImGuiID id, const ImVec2& size); + IMGUIEX_CANVAS_API bool Begin(const char* id, const ImVec2& size); + IMGUIEX_CANVAS_API bool Begin(ImGuiID id, const ImVec2& size); // Ends interaction with canvas plane. // // Must be called only when Begin() retuned true. - void End(); + IMGUIEX_CANVAS_API void End(); // Sets visible region of canvas plane. // @@ -120,50 +124,50 @@ struct Canvas // corner of the canvas. // // Scale greater than 1 make canvas content be bigger, less than 1 smaller. - void SetView(const ImVec2& origin, float scale); - void SetView(const CanvasView& view); + IMGUIEX_CANVAS_API void SetView(const ImVec2& origin, float scale); + IMGUIEX_CANVAS_API void SetView(const CanvasView& view); // Centers view over specific point on canvas plane. // // View will be centered on specific point by changing origin // but not scale. - void CenterView(const ImVec2& canvasPoint); + IMGUIEX_CANVAS_API void CenterView(const ImVec2& canvasPoint); // Calculates view over specific point on canvas plane. - CanvasView CalcCenterView(const ImVec2& canvasPoint) const; + IMGUIEX_CANVAS_API CanvasView CalcCenterView(const ImVec2& canvasPoint) const; // Centers view over specific rectangle on canvas plane. // // Whole rectangle will fit in canvas view. This will affect both // origin and scale. - void CenterView(const ImRect& canvasRect); + IMGUIEX_CANVAS_API void CenterView(const ImRect& canvasRect); // Calculates view over specific rectangle on canvas plane. - CanvasView CalcCenterView(const ImRect& canvasRect) const; + IMGUIEX_CANVAS_API CanvasView CalcCenterView(const ImRect& canvasRect) const; // Suspends canvas by returning to normal ImGui transformation space. // While suspended UI will not be drawn on canvas plane. // // Calls to Suspend()/Resume() are symetrical. Each call to Suspend() // must be matched with call to Resume(). - void Suspend(); - void Resume(); + IMGUIEX_CANVAS_API void Suspend(); + IMGUIEX_CANVAS_API void Resume(); // Transforms point from canvas plane to ImGui. - ImVec2 FromLocal(const ImVec2& point) const; - ImVec2 FromLocal(const ImVec2& point, const CanvasView& view) const; + IMGUIEX_CANVAS_API ImVec2 FromLocal(const ImVec2& point) const; + IMGUIEX_CANVAS_API ImVec2 FromLocal(const ImVec2& point, const CanvasView& view) const; // Transforms vector from canvas plant to ImGui. - ImVec2 FromLocalV(const ImVec2& vector) const; - ImVec2 FromLocalV(const ImVec2& vector, const CanvasView& view) const; + IMGUIEX_CANVAS_API ImVec2 FromLocalV(const ImVec2& vector) const; + IMGUIEX_CANVAS_API ImVec2 FromLocalV(const ImVec2& vector, const CanvasView& view) const; // Transforms point from ImGui to canvas plane. - ImVec2 ToLocal(const ImVec2& point) const; - ImVec2 ToLocal(const ImVec2& point, const CanvasView& view) const; + IMGUIEX_CANVAS_API ImVec2 ToLocal(const ImVec2& point) const; + IMGUIEX_CANVAS_API ImVec2 ToLocal(const ImVec2& point, const CanvasView& view) const; // Transforms vector from ImGui to canvas plane. - ImVec2 ToLocalV(const ImVec2& vector) const; - ImVec2 ToLocalV(const ImVec2& vector, const CanvasView& view) const; + IMGUIEX_CANVAS_API ImVec2 ToLocalV(const ImVec2& vector) const; + IMGUIEX_CANVAS_API ImVec2 ToLocalV(const ImVec2& vector, const CanvasView& view) const; // Returns widget bounds. // @@ -175,7 +179,7 @@ struct Canvas const ImRect& ViewRect() const { return m_ViewRect; } // Calculates visible region for view. - ImRect CalcViewRect(const CanvasView& view) const; + IMGUIEX_CANVAS_API ImRect CalcViewRect(const CanvasView& view) const; // Returns current view. const CanvasView& View() const { return m_View; } @@ -232,6 +236,7 @@ private: Range* m_CurrentRange = nullptr; # endif + int m_DrawListFirstCommandIndex = 0; int m_DrawListCommadBufferSize = 0; int m_DrawListStartVertexIndex = 0; diff --git a/3rdparty/imgui-node-editor/imgui_extra_math.h b/3rdparty/imgui-node-editor/imgui_extra_math.h index 3022055..3df615a 100644 --- a/3rdparty/imgui-node-editor/imgui_extra_math.h +++ b/3rdparty/imgui-node-editor/imgui_extra_math.h @@ -15,10 +15,10 @@ //------------------------------------------------------------------------------ -# include # ifndef IMGUI_DEFINE_MATH_OPERATORS # define IMGUI_DEFINE_MATH_OPERATORS # endif +# include # include @@ -30,10 +30,14 @@ struct ImLine //------------------------------------------------------------------------------ +# if IMGUI_VERSION_NUM < 19002 inline bool operator==(const ImVec2& lhs, const ImVec2& rhs); inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs); +# endif inline ImVec2 operator*(const float lhs, const ImVec2& rhs); +# if IMGUI_VERSION_NUM < 18955 inline ImVec2 operator-(const ImVec2& lhs); +# endif //------------------------------------------------------------------------------ diff --git a/3rdparty/imgui-node-editor/imgui_extra_math.inl b/3rdparty/imgui-node-editor/imgui_extra_math.inl index 13cf990..8e2347f 100644 --- a/3rdparty/imgui-node-editor/imgui_extra_math.inl +++ b/3rdparty/imgui-node-editor/imgui_extra_math.inl @@ -19,6 +19,7 @@ //------------------------------------------------------------------------------ +# if IMGUI_VERSION_NUM < 19002 inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; @@ -28,16 +29,19 @@ inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; } +# endif inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); } +# if IMGUI_VERSION_NUM < 18955 inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); } +# endif //------------------------------------------------------------------------------ diff --git a/3rdparty/imgui-node-editor/imgui_node_editor.cpp b/3rdparty/imgui-node-editor/imgui_node_editor.cpp index cd18324..1d2bb06 100644 --- a/3rdparty/imgui-node-editor/imgui_node_editor.cpp +++ b/3rdparty/imgui-node-editor/imgui_node_editor.cpp @@ -1,10 +1,3 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - //------------------------------------------------------------------------------ // VERSION 0.9.1 // @@ -42,6 +35,58 @@ static bool const value = sizeof(test(0)) == sizeof(yes); \ }; + +namespace ax { +namespace NodeEditor { +namespace Detail { + +# if !defined(IMGUI_VERSION_NUM) || (IMGUI_VERSION_NUM < 18822) +# define DECLARE_KEY_TESTER(Key) \ + DECLARE_HAS_NESTED(Key, Key) \ + struct KeyTester_ ## Key \ + { \ + template \ + static int Get(typename std::enable_if::value, T>::type*) \ + { \ + return ImGui::GetKeyIndex(T::Key); \ + } \ + \ + template \ + static int Get(typename std::enable_if::value, T>::type*) \ + { \ + return -1; \ + } \ + } + +DECLARE_KEY_TESTER(ImGuiKey_F); +DECLARE_KEY_TESTER(ImGuiKey_D); + +static inline int GetKeyIndexForF() +{ + return KeyTester_ImGuiKey_F::Get(nullptr); +} + +static inline int GetKeyIndexForD() +{ + return KeyTester_ImGuiKey_D::Get(nullptr); +} +# else +static inline ImGuiKey GetKeyIndexForF() +{ + return ImGuiKey_F; +} + +static inline ImGuiKey GetKeyIndexForD() +{ + return ImGuiKey_D; +} +# endif + +} // namespace Detail +} // namespace NodeEditor +} // namespace ax + + //------------------------------------------------------------------------------ namespace ed = ax::NodeEditor::Detail; @@ -169,34 +214,34 @@ static void ImDrawListSplitter_Grow(ImDrawList* draw_list, ImDrawListSplitter* s static void ImDrawList_ChannelsGrow(ImDrawList* draw_list, int channels_count) { - ImDrawListSplitter_Grow(draw_list, &draw_list->_Splitter, channels_count); + ImDrawListSplitter_Grow(draw_list, &draw_list->_Splitter, channels_count); } static void ImDrawListSplitter_SwapChannels(ImDrawListSplitter* splitter, int left, int right) { - IM_ASSERT(left < splitter->_Count && right < splitter->_Count); - if (left == right) - return; + IM_ASSERT(left < splitter->_Count && right < splitter->_Count); + if (left == right) + return; - auto currentChannel = splitter->_Current; + auto currentChannel = splitter->_Current; - auto* leftCmdBuffer = &splitter->_Channels[left]._CmdBuffer; - auto* leftIdxBuffer = &splitter->_Channels[left]._IdxBuffer; - auto* rightCmdBuffer = &splitter->_Channels[right]._CmdBuffer; - auto* rightIdxBuffer = &splitter->_Channels[right]._IdxBuffer; + auto* leftCmdBuffer = &splitter->_Channels[left]._CmdBuffer; + auto* leftIdxBuffer = &splitter->_Channels[left]._IdxBuffer; + auto* rightCmdBuffer = &splitter->_Channels[right]._CmdBuffer; + auto* rightIdxBuffer = &splitter->_Channels[right]._IdxBuffer; - leftCmdBuffer->swap(*rightCmdBuffer); - leftIdxBuffer->swap(*rightIdxBuffer); + leftCmdBuffer->swap(*rightCmdBuffer); + leftIdxBuffer->swap(*rightIdxBuffer); - if (currentChannel == left) - splitter->_Current = right; - else if (currentChannel == right) - splitter->_Current = left; + if (currentChannel == left) + splitter->_Current = right; + else if (currentChannel == right) + splitter->_Current = left; } static void ImDrawList_SwapChannels(ImDrawList* drawList, int left, int right) { - ImDrawListSplitter_SwapChannels(&drawList->_Splitter, left, right); + ImDrawListSplitter_SwapChannels(&drawList->_Splitter, left, right); } static void ImDrawList_SwapSplitter(ImDrawList* drawList, ImDrawListSplitter& splitter) @@ -655,7 +700,7 @@ void ed::Node::Draw(ImDrawList* drawList, DrawFlags flags) drawList->ChannelsSetCurrent(m_Channel + c_NodeBaseChannel); - DrawBorder(drawList, borderColor, editorStyle.SelectedNodeBorderWidth); + DrawBorder(drawList, borderColor, editorStyle.SelectedNodeBorderWidth, editorStyle.SelectedNodeBorderOffset); } else if (!IsGroup(this) && (flags & Hovered)) { @@ -664,16 +709,18 @@ void ed::Node::Draw(ImDrawList* drawList, DrawFlags flags) drawList->ChannelsSetCurrent(m_Channel + c_NodeBaseChannel); - DrawBorder(drawList, borderColor, editorStyle.HoveredNodeBorderWidth); + DrawBorder(drawList, borderColor, editorStyle.HoveredNodeBorderWidth, editorStyle.HoverNodeBorderOffset); } } -void ed::Node::DrawBorder(ImDrawList* drawList, ImU32 color, float thickness) +void ed::Node::DrawBorder(ImDrawList* drawList, ImU32 color, float thickness, float offset) { if (thickness > 0.0f) { - drawList->AddRect(m_Bounds.Min, m_Bounds.Max, - color, m_Rounding, c_AllRoundCornersFlags, thickness); + const ImVec2 extraOffset = ImVec2(offset, offset); + + drawList->AddRect(m_Bounds.Min - extraOffset, m_Bounds.Max + extraOffset, + color, ImMax(0.0f, m_Rounding + offset), c_AllRoundCornersFlags, thickness); } } @@ -1090,9 +1137,9 @@ void ed::EditorContext::Begin(const char* id, const ImVec2& size) if (!m_IsInitialized) { - // Cycle canvas so it has a change to setup its size before settings are loaded - m_Canvas.Begin(id, canvasSize); - m_Canvas.End(); + // Cycle canvas, so it has a chance to initialize its size before settings are loaded + if (m_Canvas.Begin(id, canvasSize)) + m_Canvas.End(); LoadSettings(); m_IsInitialized = true; @@ -1161,7 +1208,7 @@ void ed::EditorContext::Begin(const char* id, const ImVec2& size) auto centerY = (previousVisibleRect.Max.y + previousVisibleRect.Min.y) * 0.5f; auto currentVisibleRect = m_Canvas.ViewRect(); auto currentAspectRatio = currentVisibleRect.GetHeight() ? (currentVisibleRect.GetWidth() / currentVisibleRect.GetHeight()) : 0.0f; - auto width = previousVisibleRect.GetHeight(); + auto width = previousVisibleRect.GetWidth(); auto height = previousVisibleRect.GetHeight(); if (m_Config.CanvasSizeMode == ax::NodeEditor::CanvasSizeMode::FitVerticalView) @@ -1918,7 +1965,8 @@ void ed::EditorContext::Suspend(SuspendFlags flags) IM_ASSERT(m_DrawList != nullptr && "Suspend was called outiside of Begin/End."); auto lastChannel = m_DrawList->_Splitter._Current; m_DrawList->ChannelsSetCurrent(m_ExternalChannel); - m_Canvas.Suspend(); + if (m_IsCanvasVisible) + m_Canvas.Suspend(); m_DrawList->ChannelsSetCurrent(lastChannel); if ((flags & SuspendFlags::KeepSplitter) != SuspendFlags::KeepSplitter) ImDrawList_SwapSplitter(m_DrawList, m_Splitter); @@ -1931,13 +1979,14 @@ void ed::EditorContext::Resume(SuspendFlags flags) ImDrawList_SwapSplitter(m_DrawList, m_Splitter); auto lastChannel = m_DrawList->_Splitter._Current; m_DrawList->ChannelsSetCurrent(m_ExternalChannel); - m_Canvas.Resume(); + if (m_IsCanvasVisible) + m_Canvas.Resume(); m_DrawList->ChannelsSetCurrent(lastChannel); } bool ed::EditorContext::IsSuspended() { - return m_Canvas.IsSuspended(); + return m_Canvas.IsSuspended(); } bool ed::EditorContext::IsFocused() @@ -2513,9 +2562,12 @@ ed::Control ed::EditorContext::BuildControl(bool allowOffscreen) if (!allowOffscreen && !m_IsHovered) return Control(); -# if IMGUI_VERSION_NUM >= 17909 +# if IMGUI_VERSION_NUM >= 18836 if (m_IsHoveredWithoutOverlapp) ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY); +# elif IMGUI_VERSION_NUM >= 17909 + if (m_IsHoveredWithoutOverlapp) + ImGui::SetItemUsingMouseWheel(); # endif return Control(hotObject, activeObject, clickedObject, doubleClickedObject, @@ -3281,7 +3333,7 @@ ed::EditorAction::AcceptResult ed::NavigateAction::Accept(const Control& control auto& io = ImGui::GetIO(); - if (Editor->CanAcceptUserInput() && ImGui::IsKeyPressed(ImGuiKey_F) && Editor->AreShortcutsEnabled()) + if (Editor->CanAcceptUserInput() && ImGui::IsKeyPressed(GetKeyIndexForF()) && Editor->AreShortcutsEnabled()) { const auto zoomMode = io.KeyShift ? NavigateAction::ZoomMode::WithMargin : NavigateAction::ZoomMode::None; @@ -3397,8 +3449,7 @@ bool ed::NavigateAction::HandleZoom(const Control& control) m_Animation.Finish(); auto mousePos = io.MousePos; - auto steps = (int)io.MouseWheel; - auto newZoom = MatchZoom(steps, m_ZoomLevels[steps < 0 ? 0 : m_ZoomLevelCount - 1]); + auto newZoom = GetNextZoom(io.MouseWheel); auto oldView = GetView(); m_Zoom = newZoom; @@ -3574,6 +3625,32 @@ ImRect ed::NavigateAction::GetViewRect() const return m_Canvas.CalcViewRect(GetView()); } +float ed::NavigateAction::GetNextZoom(float steps) +{ + if (this->Editor->GetConfig().EnableSmoothZoom) + { + return MatchSmoothZoom(steps); + } + else + { + auto fixedSteps = (int)steps; + return MatchZoom(fixedSteps, m_ZoomLevels[fixedSteps < 0 ? 0 : m_ZoomLevelCount - 1]); + } +} + +float ed::NavigateAction::MatchSmoothZoom(float steps) +{ + const auto power = Editor->GetConfig().SmoothZoomPower; + + const auto newZoom = m_Zoom * powf(power, steps); + if (newZoom < m_ZoomLevels[0]) + return m_ZoomLevels[0]; + else if (newZoom > m_ZoomLevels[m_ZoomLevelCount - 1]) + return m_ZoomLevels[m_ZoomLevelCount - 1]; + else + return newZoom; +} + float ed::NavigateAction::MatchZoom(int steps, float fallbackZoom) { auto currentZoomIndex = MatchZoomIndex(steps); @@ -4320,7 +4397,7 @@ ed::EditorAction::AcceptResult ed::ShortcutAction::Accept(const Control& control candidateAction = Copy; if (io.KeyCtrl && !io.KeyShift && !io.KeyAlt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V))) candidateAction = Paste; - if (io.KeyCtrl && !io.KeyShift && !io.KeyAlt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_D))) + if (io.KeyCtrl && !io.KeyShift && !io.KeyAlt && ImGui::IsKeyPressed(GetKeyIndexForD())) candidateAction = Duplicate; if (!io.KeyCtrl && !io.KeyShift && !io.KeyAlt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space))) candidateAction = CreateNode; @@ -5650,6 +5727,8 @@ float* ed::Style::GetVarFloatAddr(StyleVar idx) case StyleVar_GroupBorderWidth: return &GroupBorderWidth; case StyleVar_HighlightConnectedLinks: return &HighlightConnectedLinks; case StyleVar_SnapLinkToPinDir: return &SnapLinkToPinDir; + case StyleVar_HoveredNodeBorderOffset: return &HoverNodeBorderOffset; + case StyleVar_SelectedNodeBorderOffset: return &SelectedNodeBorderOffset; default: return nullptr; } } @@ -5774,7 +5853,3 @@ void ed::Config::EndSave() if (EndSaveSession) EndSaveSession(UserPointer); } - -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif diff --git a/3rdparty/imgui-node-editor/imgui_node_editor.h b/3rdparty/imgui-node-editor/imgui_node_editor.h index 400c0d7..c79f41a 100644 --- a/3rdparty/imgui-node-editor/imgui_node_editor.h +++ b/3rdparty/imgui-node-editor/imgui_node_editor.h @@ -15,15 +15,20 @@ //------------------------------------------------------------------------------ -#define IMGUI_DEFINE_MATH_OPERATORS # include # include // std::uintXX_t # include // std::move //------------------------------------------------------------------------------ -# define IMGUI_NODE_EDITOR_VERSION "0.9.2" -# define IMGUI_NODE_EDITOR_VERSION_NUM 000902 +# define IMGUI_NODE_EDITOR_VERSION "0.9.4" +# define IMGUI_NODE_EDITOR_VERSION_NUM 000904 + + +//------------------------------------------------------------------------------ +#ifndef IMGUI_NODE_EDITOR_API +#define IMGUI_NODE_EDITOR_API +#endif //------------------------------------------------------------------------------ @@ -100,6 +105,8 @@ struct Config int SelectButtonIndex; // Mouse button index select action will react to (0-left, 1-right, 2-middle) int NavigateButtonIndex; // Mouse button index navigate action will react to (0-left, 1-right, 2-middle) int ContextMenuButtonIndex; // Mouse button index context menu action will react to (0-left, 1-right, 2-middle) + bool EnableSmoothZoom; + float SmoothZoomPower; Config() : SettingsFile("NodeEditor.json") @@ -116,6 +123,12 @@ struct Config , SelectButtonIndex(0) , NavigateButtonIndex(1) , ContextMenuButtonIndex(1) + , EnableSmoothZoom(false) +# ifdef __APPLE__ + , SmoothZoomPower(1.1f) +# else + , SmoothZoomPower(1.3f) +# endif { } }; @@ -174,6 +187,8 @@ enum StyleVar StyleVar_GroupBorderWidth, StyleVar_HighlightConnectedLinks, StyleVar_SnapLinkToPinDir, + StyleVar_HoveredNodeBorderOffset, + StyleVar_SelectedNodeBorderOffset, StyleVar_Count }; @@ -184,7 +199,9 @@ struct Style float NodeRounding; float NodeBorderWidth; float HoveredNodeBorderWidth; + float HoverNodeBorderOffset; float SelectedNodeBorderWidth; + float SelectedNodeBorderOffset; float PinRounding; float PinBorderWidth; float LinkStrength; @@ -209,35 +226,37 @@ struct Style Style() { - NodePadding = ImVec4(8, 8, 8, 8); - NodeRounding = 12.0f; - NodeBorderWidth = 1.5f; - HoveredNodeBorderWidth = 3.5f; - SelectedNodeBorderWidth = 3.5f; - PinRounding = 4.0f; - PinBorderWidth = 0.0f; - LinkStrength = 100.0f; - SourceDirection = ImVec2(1.0f, 0.0f); - TargetDirection = ImVec2(-1.0f, 0.0f); - ScrollDuration = 0.35f; - FlowMarkerDistance = 30.0f; - FlowSpeed = 150.0f; - FlowDuration = 2.0f; - PivotAlignment = ImVec2(0.5f, 0.5f); - PivotSize = ImVec2(0.0f, 0.0f); - PivotScale = ImVec2(1, 1); + NodePadding = ImVec4(8, 8, 8, 8); + NodeRounding = 12.0f; + NodeBorderWidth = 1.5f; + HoveredNodeBorderWidth = 3.5f; + HoverNodeBorderOffset = 0.0f; + SelectedNodeBorderWidth = 3.5f; + SelectedNodeBorderOffset = 0.0f; + PinRounding = 4.0f; + PinBorderWidth = 0.0f; + LinkStrength = 100.0f; + SourceDirection = ImVec2(1.0f, 0.0f); + TargetDirection = ImVec2(-1.0f, 0.0f); + ScrollDuration = 0.35f; + FlowMarkerDistance = 30.0f; + FlowSpeed = 150.0f; + FlowDuration = 2.0f; + PivotAlignment = ImVec2(0.5f, 0.5f); + PivotSize = ImVec2(0.0f, 0.0f); + PivotScale = ImVec2(1, 1); #if IMGUI_VERSION_NUM > 18101 - PinCorners = ImDrawFlags_RoundCornersAll; + PinCorners = ImDrawFlags_RoundCornersAll; #else - PinCorners = ImDrawCornerFlags_All; + PinCorners = ImDrawCornerFlags_All; #endif - PinRadius = 0.0f; - PinArrowSize = 0.0f; - PinArrowWidth = 0.0f; - GroupRounding = 6.0f; - GroupBorderWidth = 1.0f; - HighlightConnectedLinks = 0.0f; - SnapLinkToPinDir = 0.0f; + PinRadius = 0.0f; + PinArrowSize = 0.0f; + PinArrowWidth = 0.0f; + GroupRounding = 6.0f; + GroupBorderWidth = 1.0f; + HighlightConnectedLinks = 0.0f; + SnapLinkToPinDir = 0.0f; Colors[StyleColor_Bg] = ImColor( 60, 60, 70, 200); Colors[StyleColor_Grid] = ImColor(120, 120, 120, 40); @@ -267,150 +286,150 @@ struct EditorContext; //------------------------------------------------------------------------------ -void SetCurrentEditor(EditorContext* ctx); -EditorContext* GetCurrentEditor(); -EditorContext* CreateEditor(const Config* config = nullptr); -void DestroyEditor(EditorContext* ctx); -const Config& GetConfig(EditorContext* ctx = nullptr); +IMGUI_NODE_EDITOR_API void SetCurrentEditor(EditorContext* ctx); +IMGUI_NODE_EDITOR_API EditorContext* GetCurrentEditor(); +IMGUI_NODE_EDITOR_API EditorContext* CreateEditor(const Config* config = nullptr); +IMGUI_NODE_EDITOR_API void DestroyEditor(EditorContext* ctx); +IMGUI_NODE_EDITOR_API const Config& GetConfig(EditorContext* ctx = nullptr); -Style& GetStyle(); -const char* GetStyleColorName(StyleColor colorIndex); +IMGUI_NODE_EDITOR_API Style& GetStyle(); +IMGUI_NODE_EDITOR_API const char* GetStyleColorName(StyleColor colorIndex); -void PushStyleColor(StyleColor colorIndex, const ImVec4& color); -void PopStyleColor(int count = 1); +IMGUI_NODE_EDITOR_API void PushStyleColor(StyleColor colorIndex, const ImVec4& color); +IMGUI_NODE_EDITOR_API void PopStyleColor(int count = 1); -void PushStyleVar(StyleVar varIndex, float value); -void PushStyleVar(StyleVar varIndex, const ImVec2& value); -void PushStyleVar(StyleVar varIndex, const ImVec4& value); -void PopStyleVar(int count = 1); +IMGUI_NODE_EDITOR_API void PushStyleVar(StyleVar varIndex, float value); +IMGUI_NODE_EDITOR_API void PushStyleVar(StyleVar varIndex, const ImVec2& value); +IMGUI_NODE_EDITOR_API void PushStyleVar(StyleVar varIndex, const ImVec4& value); +IMGUI_NODE_EDITOR_API void PopStyleVar(int count = 1); -void Begin(const char* id, const ImVec2& size = ImVec2(0, 0)); -void End(); +IMGUI_NODE_EDITOR_API void Begin(const char* id, const ImVec2& size = ImVec2(0, 0)); +IMGUI_NODE_EDITOR_API void End(); -void BeginNode(NodeId id); -void BeginPin(PinId id, PinKind kind); -void PinRect(const ImVec2& a, const ImVec2& b); -void PinPivotRect(const ImVec2& a, const ImVec2& b); -void PinPivotSize(const ImVec2& size); -void PinPivotScale(const ImVec2& scale); -void PinPivotAlignment(const ImVec2& alignment); -void EndPin(); -void Group(const ImVec2& size); -void EndNode(); +IMGUI_NODE_EDITOR_API void BeginNode(NodeId id); +IMGUI_NODE_EDITOR_API void BeginPin(PinId id, PinKind kind); +IMGUI_NODE_EDITOR_API void PinRect(const ImVec2& a, const ImVec2& b); +IMGUI_NODE_EDITOR_API void PinPivotRect(const ImVec2& a, const ImVec2& b); +IMGUI_NODE_EDITOR_API void PinPivotSize(const ImVec2& size); +IMGUI_NODE_EDITOR_API void PinPivotScale(const ImVec2& scale); +IMGUI_NODE_EDITOR_API void PinPivotAlignment(const ImVec2& alignment); +IMGUI_NODE_EDITOR_API void EndPin(); +IMGUI_NODE_EDITOR_API void Group(const ImVec2& size); +IMGUI_NODE_EDITOR_API void EndNode(); -bool BeginGroupHint(NodeId nodeId); -ImVec2 GetGroupMin(); -ImVec2 GetGroupMax(); -ImDrawList* GetHintForegroundDrawList(); -ImDrawList* GetHintBackgroundDrawList(); -void EndGroupHint(); +IMGUI_NODE_EDITOR_API bool BeginGroupHint(NodeId nodeId); +IMGUI_NODE_EDITOR_API ImVec2 GetGroupMin(); +IMGUI_NODE_EDITOR_API ImVec2 GetGroupMax(); +IMGUI_NODE_EDITOR_API ImDrawList* GetHintForegroundDrawList(); +IMGUI_NODE_EDITOR_API ImDrawList* GetHintBackgroundDrawList(); +IMGUI_NODE_EDITOR_API void EndGroupHint(); // TODO: Add a way to manage node background channels -ImDrawList* GetNodeBackgroundDrawList(NodeId nodeId); +IMGUI_NODE_EDITOR_API ImDrawList* GetNodeBackgroundDrawList(NodeId nodeId); -bool Link(LinkId id, PinId startPinId, PinId endPinId, const ImVec4& color = ImVec4(1, 1, 1, 1), float thickness = 1.0f); +IMGUI_NODE_EDITOR_API bool Link(LinkId id, PinId startPinId, PinId endPinId, const ImVec4& color = ImVec4(1, 1, 1, 1), float thickness = 1.0f); -void Flow(LinkId linkId, FlowDirection direction = FlowDirection::Forward); +IMGUI_NODE_EDITOR_API void Flow(LinkId linkId, FlowDirection direction = FlowDirection::Forward); -bool BeginCreate(const ImVec4& color = ImVec4(1, 1, 1, 1), float thickness = 1.0f); -bool QueryNewLink(PinId* startId, PinId* endId); -bool QueryNewLink(PinId* startId, PinId* endId, const ImVec4& color, float thickness = 1.0f); -bool QueryNewNode(PinId* pinId); -bool QueryNewNode(PinId* pinId, const ImVec4& color, float thickness = 1.0f); -bool AcceptNewItem(); -bool AcceptNewItem(const ImVec4& color, float thickness = 1.0f); -void RejectNewItem(); -void RejectNewItem(const ImVec4& color, float thickness = 1.0f); -void EndCreate(); +IMGUI_NODE_EDITOR_API bool BeginCreate(const ImVec4& color = ImVec4(1, 1, 1, 1), float thickness = 1.0f); +IMGUI_NODE_EDITOR_API bool QueryNewLink(PinId* startId, PinId* endId); +IMGUI_NODE_EDITOR_API bool QueryNewLink(PinId* startId, PinId* endId, const ImVec4& color, float thickness = 1.0f); +IMGUI_NODE_EDITOR_API bool QueryNewNode(PinId* pinId); +IMGUI_NODE_EDITOR_API bool QueryNewNode(PinId* pinId, const ImVec4& color, float thickness = 1.0f); +IMGUI_NODE_EDITOR_API bool AcceptNewItem(); +IMGUI_NODE_EDITOR_API bool AcceptNewItem(const ImVec4& color, float thickness = 1.0f); +IMGUI_NODE_EDITOR_API void RejectNewItem(); +IMGUI_NODE_EDITOR_API void RejectNewItem(const ImVec4& color, float thickness = 1.0f); +IMGUI_NODE_EDITOR_API void EndCreate(); -bool BeginDelete(); -bool QueryDeletedLink(LinkId* linkId, PinId* startId = nullptr, PinId* endId = nullptr); -bool QueryDeletedNode(NodeId* nodeId); -bool AcceptDeletedItem(bool deleteDependencies = true); -void RejectDeletedItem(); -void EndDelete(); +IMGUI_NODE_EDITOR_API bool BeginDelete(); +IMGUI_NODE_EDITOR_API bool QueryDeletedLink(LinkId* linkId, PinId* startId = nullptr, PinId* endId = nullptr); +IMGUI_NODE_EDITOR_API bool QueryDeletedNode(NodeId* nodeId); +IMGUI_NODE_EDITOR_API bool AcceptDeletedItem(bool deleteDependencies = true); +IMGUI_NODE_EDITOR_API void RejectDeletedItem(); +IMGUI_NODE_EDITOR_API void EndDelete(); -void SetNodePosition(NodeId nodeId, const ImVec2& editorPosition); -void SetGroupSize(NodeId nodeId, const ImVec2& size); -ImVec2 GetNodePosition(NodeId nodeId); -ImVec2 GetNodeSize(NodeId nodeId); -void CenterNodeOnScreen(NodeId nodeId); -void SetNodeZPosition(NodeId nodeId, float z); // Sets node z position, nodes with higher value are drawn over nodes with lower value -float GetNodeZPosition(NodeId nodeId); // Returns node z position, defaults is 0.0f +IMGUI_NODE_EDITOR_API void SetNodePosition(NodeId nodeId, const ImVec2& editorPosition); +IMGUI_NODE_EDITOR_API void SetGroupSize(NodeId nodeId, const ImVec2& size); +IMGUI_NODE_EDITOR_API ImVec2 GetNodePosition(NodeId nodeId); +IMGUI_NODE_EDITOR_API ImVec2 GetNodeSize(NodeId nodeId); +IMGUI_NODE_EDITOR_API void CenterNodeOnScreen(NodeId nodeId); +IMGUI_NODE_EDITOR_API void SetNodeZPosition(NodeId nodeId, float z); // Sets node z position, nodes with higher value are drawn over nodes with lower value +IMGUI_NODE_EDITOR_API float GetNodeZPosition(NodeId nodeId); // Returns node z position, defaults is 0.0f -void RestoreNodeState(NodeId nodeId); +IMGUI_NODE_EDITOR_API void RestoreNodeState(NodeId nodeId); -void Suspend(); -void Resume(); -bool IsSuspended(); +IMGUI_NODE_EDITOR_API void Suspend(); +IMGUI_NODE_EDITOR_API void Resume(); +IMGUI_NODE_EDITOR_API bool IsSuspended(); -bool IsActive(); +IMGUI_NODE_EDITOR_API bool IsActive(); -bool HasSelectionChanged(); -int GetSelectedObjectCount(); -int GetSelectedNodes(NodeId* nodes, int size); -int GetSelectedLinks(LinkId* links, int size); -bool IsNodeSelected(NodeId nodeId); -bool IsLinkSelected(LinkId linkId); -void ClearSelection(); -void SelectNode(NodeId nodeId, bool append = false); -void SelectLink(LinkId linkId, bool append = false); -void DeselectNode(NodeId nodeId); -void DeselectLink(LinkId linkId); +IMGUI_NODE_EDITOR_API bool HasSelectionChanged(); +IMGUI_NODE_EDITOR_API int GetSelectedObjectCount(); +IMGUI_NODE_EDITOR_API int GetSelectedNodes(NodeId* nodes, int size); +IMGUI_NODE_EDITOR_API int GetSelectedLinks(LinkId* links, int size); +IMGUI_NODE_EDITOR_API bool IsNodeSelected(NodeId nodeId); +IMGUI_NODE_EDITOR_API bool IsLinkSelected(LinkId linkId); +IMGUI_NODE_EDITOR_API void ClearSelection(); +IMGUI_NODE_EDITOR_API void SelectNode(NodeId nodeId, bool append = false); +IMGUI_NODE_EDITOR_API void SelectLink(LinkId linkId, bool append = false); +IMGUI_NODE_EDITOR_API void DeselectNode(NodeId nodeId); +IMGUI_NODE_EDITOR_API void DeselectLink(LinkId linkId); -bool DeleteNode(NodeId nodeId); -bool DeleteLink(LinkId linkId); +IMGUI_NODE_EDITOR_API bool DeleteNode(NodeId nodeId); +IMGUI_NODE_EDITOR_API bool DeleteLink(LinkId linkId); -bool HasAnyLinks(NodeId nodeId); // Returns true if node has any link connected -bool HasAnyLinks(PinId pinId); // Return true if pin has any link connected -int BreakLinks(NodeId nodeId); // Break all links connected to this node -int BreakLinks(PinId pinId); // Break all links connected to this pin +IMGUI_NODE_EDITOR_API bool HasAnyLinks(NodeId nodeId); // Returns true if node has any link connected +IMGUI_NODE_EDITOR_API bool HasAnyLinks(PinId pinId); // Return true if pin has any link connected +IMGUI_NODE_EDITOR_API int BreakLinks(NodeId nodeId); // Break all links connected to this node +IMGUI_NODE_EDITOR_API int BreakLinks(PinId pinId); // Break all links connected to this pin -void NavigateToContent(float duration = -1); -void NavigateToSelection(bool zoomIn = false, float duration = -1); +IMGUI_NODE_EDITOR_API void NavigateToContent(float duration = -1); +IMGUI_NODE_EDITOR_API void NavigateToSelection(bool zoomIn = false, float duration = -1); -bool ShowNodeContextMenu(NodeId* nodeId); -bool ShowPinContextMenu(PinId* pinId); -bool ShowLinkContextMenu(LinkId* linkId); -bool ShowBackgroundContextMenu(); +IMGUI_NODE_EDITOR_API bool ShowNodeContextMenu(NodeId* nodeId); +IMGUI_NODE_EDITOR_API bool ShowPinContextMenu(PinId* pinId); +IMGUI_NODE_EDITOR_API bool ShowLinkContextMenu(LinkId* linkId); +IMGUI_NODE_EDITOR_API bool ShowBackgroundContextMenu(); -void EnableShortcuts(bool enable); -bool AreShortcutsEnabled(); +IMGUI_NODE_EDITOR_API void EnableShortcuts(bool enable); +IMGUI_NODE_EDITOR_API bool AreShortcutsEnabled(); -bool BeginShortcut(); -bool AcceptCut(); -bool AcceptCopy(); -bool AcceptPaste(); -bool AcceptDuplicate(); -bool AcceptCreateNode(); -int GetActionContextSize(); -int GetActionContextNodes(NodeId* nodes, int size); -int GetActionContextLinks(LinkId* links, int size); -void EndShortcut(); +IMGUI_NODE_EDITOR_API bool BeginShortcut(); +IMGUI_NODE_EDITOR_API bool AcceptCut(); +IMGUI_NODE_EDITOR_API bool AcceptCopy(); +IMGUI_NODE_EDITOR_API bool AcceptPaste(); +IMGUI_NODE_EDITOR_API bool AcceptDuplicate(); +IMGUI_NODE_EDITOR_API bool AcceptCreateNode(); +IMGUI_NODE_EDITOR_API int GetActionContextSize(); +IMGUI_NODE_EDITOR_API int GetActionContextNodes(NodeId* nodes, int size); +IMGUI_NODE_EDITOR_API int GetActionContextLinks(LinkId* links, int size); +IMGUI_NODE_EDITOR_API void EndShortcut(); -float GetCurrentZoom(); +IMGUI_NODE_EDITOR_API float GetCurrentZoom(); -NodeId GetHoveredNode(); -PinId GetHoveredPin(); -LinkId GetHoveredLink(); -NodeId GetDoubleClickedNode(); -PinId GetDoubleClickedPin(); -LinkId GetDoubleClickedLink(); -bool IsBackgroundClicked(); -bool IsBackgroundDoubleClicked(); -ImGuiMouseButton GetBackgroundClickButtonIndex(); // -1 if none -ImGuiMouseButton GetBackgroundDoubleClickButtonIndex(); // -1 if none +IMGUI_NODE_EDITOR_API NodeId GetHoveredNode(); +IMGUI_NODE_EDITOR_API PinId GetHoveredPin(); +IMGUI_NODE_EDITOR_API LinkId GetHoveredLink(); +IMGUI_NODE_EDITOR_API NodeId GetDoubleClickedNode(); +IMGUI_NODE_EDITOR_API PinId GetDoubleClickedPin(); +IMGUI_NODE_EDITOR_API LinkId GetDoubleClickedLink(); +IMGUI_NODE_EDITOR_API bool IsBackgroundClicked(); +IMGUI_NODE_EDITOR_API bool IsBackgroundDoubleClicked(); +IMGUI_NODE_EDITOR_API ImGuiMouseButton GetBackgroundClickButtonIndex(); // -1 if none +IMGUI_NODE_EDITOR_API ImGuiMouseButton GetBackgroundDoubleClickButtonIndex(); // -1 if none -bool GetLinkPins(LinkId linkId, PinId* startPinId, PinId* endPinId); // pass nullptr if particular pin do not interest you +IMGUI_NODE_EDITOR_API bool GetLinkPins(LinkId linkId, PinId* startPinId, PinId* endPinId); // pass nullptr if particular pin do not interest you -bool PinHadAnyLinks(PinId pinId); +IMGUI_NODE_EDITOR_API bool PinHadAnyLinks(PinId pinId); -ImVec2 GetScreenSize(); -ImVec2 ScreenToCanvas(const ImVec2& pos); -ImVec2 CanvasToScreen(const ImVec2& pos); +IMGUI_NODE_EDITOR_API ImVec2 GetScreenSize(); +IMGUI_NODE_EDITOR_API ImVec2 ScreenToCanvas(const ImVec2& pos); +IMGUI_NODE_EDITOR_API ImVec2 CanvasToScreen(const ImVec2& pos); -int GetNodeCount(); // Returns number of submitted nodes since Begin() call -int GetOrderedNodeIds(NodeId* nodes, int size); // Fills an array with node id's in order they're drawn; up to 'size` elements are set. Returns actual size of filled id's. +IMGUI_NODE_EDITOR_API int GetNodeCount(); // Returns number of submitted nodes since Begin() call +IMGUI_NODE_EDITOR_API int GetOrderedNodeIds(NodeId* nodes, int size); // Fills an array with node id's in order they're drawn; up to 'size` elements are set. Returns actual size of filled id's. diff --git a/3rdparty/imgui-node-editor/imgui_node_editor_api.cpp b/3rdparty/imgui-node-editor/imgui_node_editor_api.cpp index 7433085..c8c7c3f 100644 --- a/3rdparty/imgui-node-editor/imgui_node_editor_api.cpp +++ b/3rdparty/imgui-node-editor/imgui_node_editor_api.cpp @@ -1,10 +1,3 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - //------------------------------------------------------------------------------ // VERSION 0.9.1 // @@ -767,8 +760,3 @@ int ax::NodeEditor::GetOrderedNodeIds(NodeId* nodes, int size) { return s_Editor->GetNodeIds(nodes, size); } - -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif diff --git a/3rdparty/imgui-node-editor/imgui_node_editor_internal.h b/3rdparty/imgui-node-editor/imgui_node_editor_internal.h index fd2bfac..0d018cf 100644 --- a/3rdparty/imgui-node-editor/imgui_node_editor_internal.h +++ b/3rdparty/imgui-node-editor/imgui_node_editor_internal.h @@ -1,10 +1,3 @@ -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - //------------------------------------------------------------------------------ // VERSION 0.9.1 // @@ -22,12 +15,14 @@ //------------------------------------------------------------------------------ +# ifndef IMGUI_DEFINE_MATH_OPERATORS +# define IMGUI_DEFINE_MATH_OPERATORS +# endif # include "imgui_node_editor.h" //------------------------------------------------------------------------------ # include -# define IMGUI_DEFINE_MATH_OPERATORS # include # include "imgui_extra_math.h" # include "imgui_bezier_math.h" @@ -440,7 +435,7 @@ struct Node final: Object virtual bool IsSelectable() override { return true; } virtual void Draw(ImDrawList* drawList, DrawFlags flags = None) override final; - void DrawBorder(ImDrawList* drawList, ImU32 color, float thickness = 1.0f); + void DrawBorder(ImDrawList* drawList, ImU32 color, float thickness = 1.0f, float offset = 0.0f); void GetGroupedNodes(std::vector& result, bool append = false); @@ -891,6 +886,8 @@ private: void NavigateTo(const ImRect& target, float duration = -1.0f, NavigationReason reason = NavigationReason::Unknown); + float GetNextZoom(float steps); + float MatchSmoothZoom(float steps); float MatchZoom(int steps, float fallbackZoom); int MatchZoomIndex(int direction); @@ -1561,8 +1558,3 @@ private: //------------------------------------------------------------------------------ # endif // __IMGUI_NODE_EDITOR_INTERNAL_H__ - -//Disable a bunch of warnings for now -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif