diff --git a/modules/v4d/src/detail/clvacontext.cpp b/modules/v4d/src/detail/clvacontext.cpp index 1fd864993..ff7f0ea85 100644 --- a/modules/v4d/src/detail/clvacontext.cpp +++ b/modules/v4d/src/detail/clvacontext.cpp @@ -10,8 +10,8 @@ namespace cv { namespace v4d { namespace detail { -CLVAContext::CLVAContext(V4D& v4d, FrameBufferContext& mainFbContext) : - mainFbContext_(mainFbContext), clvaFbContext_(v4d, "CLVA", mainFbContext) { +CLVAContext::CLVAContext(FrameBufferContext& mainFbContext) : + mainFbContext_(mainFbContext), clvaFbContext_("CLVA", mainFbContext) { } bool CLVAContext::capture(std::function fn, cv::UMat& output) { diff --git a/modules/v4d/src/detail/clvacontext.hpp b/modules/v4d/src/detail/clvacontext.hpp index 3b5be7ea3..9247e3e2b 100644 --- a/modules/v4d/src/detail/clvacontext.hpp +++ b/modules/v4d/src/detail/clvacontext.hpp @@ -32,7 +32,7 @@ public: * Create the CLVAContext * @param fbContext The corresponding framebuffer context */ - CLVAContext(V4D& v4d, FrameBufferContext& fbContext); + CLVAContext(FrameBufferContext& fbContext); /*! * Called to capture from a function object. * The functor fn is passed a UMat which it writes to which in turn is captured to the framebuffer. diff --git a/modules/v4d/src/detail/framebuffercontext.cpp b/modules/v4d/src/detail/framebuffercontext.cpp index e3aaef5d7..34360d7c2 100644 --- a/modules/v4d/src/detail/framebuffercontext.cpp +++ b/modules/v4d/src/detail/framebuffercontext.cpp @@ -21,19 +21,14 @@ namespace cv { namespace v4d { namespace detail { -static bool contains_absolute(nanogui::Widget* w, const nanogui::Vector2i& p) { - nanogui::Vector2i d = p - w->absolute_position(); - return d.x() >= 0 && d.y() >= 0 && d.x() < w->size().x() && d.y() < w->size().y(); -} - int frameBufferContextCnt = 0; -FrameBufferContext::FrameBufferContext(V4D& v4d, const string& title, const FrameBufferContext& other) : FrameBufferContext(v4d, other.frameBufferSize_, true, title, other.major_, other.minor_, other.compat_, other.samples_, other.debug_, other.glfwWindow_, &other) { +FrameBufferContext::FrameBufferContext(const string& title, const FrameBufferContext& other) : FrameBufferContext(other.frameBufferSize_, true, title, other.major_, other.minor_, other.compat_, other.samples_, other.debug_, other.glfwWindow_, &other) { } -FrameBufferContext::FrameBufferContext(V4D& v4d, const cv::Size& framebufferSize, bool offscreen, +FrameBufferContext::FrameBufferContext(const cv::Size& framebufferSize, bool offscreen, const string& title, int major, int minor, bool compat, int samples, bool debug, GLFWwindow* sharedWindow, const FrameBufferContext* parent) : - v4d_(&v4d), offscreen_(offscreen), title_(title), major_(major), minor_( + offscreen_(offscreen), title_(title), major_(major), minor_( minor), compat_(compat), samples_(samples), debug_(debug), viewport_(0, 0, framebufferSize.width, framebufferSize.height), frameBufferSize_(framebufferSize), isShared_(false), sharedWindow_(sharedWindow), parent_(parent), framebuffer_(framebufferSize, CV_8UC4) { run_sync_on_main<1>([this](){ init(); }); index_ = ++frameBufferContextCnt; @@ -286,106 +281,6 @@ void FrameBufferContext::init() { #endif setup(frameBufferSize_); - glfwSetWindowUserPointer(getGLFWWindow(), v4d_); - - glfwSetCursorPosCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) { - auto pt = v4d->fbCtx().toWindowCoord(cv::Point2f(x, y)); - v4d->nguiCtx().screen().cursor_pos_callback_event(pt.x, pt.y); - } -#ifndef __EMSCRIPTEN__ - auto cursor = v4d->getMousePosition(); - auto diff = cursor - cv::Vec2f(x, y); - if (v4d->isMouseDrag()) { - v4d->pan(diff[0], -diff[1]); - } -#endif - v4d->setMousePosition(x, y); - } - ); - glfwSetMouseButtonCallback(getGLFWWindow(), - [](GLFWwindow* glfwWin, int button, int action, int modifiers) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) - v4d->nguiCtx().screen().mouse_button_callback_event(button, action, modifiers); - if (button == GLFW_MOUSE_BUTTON_RIGHT) { - v4d->setMouseDrag(action == GLFW_PRESS); - } - } - ); - glfwSetKeyCallback(getGLFWWindow(), - [](GLFWwindow* glfwWin, int key, int scancode, int action, int mods) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) - v4d->nguiCtx().screen().key_callback_event(key, scancode, action, mods); - } - ); - glfwSetCharCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, unsigned int codepoint) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) - v4d->nguiCtx().screen().char_callback_event(codepoint); - } - ); - glfwSetDropCallback(getGLFWWindow(), - [](GLFWwindow* glfwWin, int count, const char** filenames) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) - v4d->nguiCtx().screen().drop_callback_event(count, filenames); - } - ); - glfwSetScrollCallback(getGLFWWindow(), - [](GLFWwindow* glfwWin, double x, double y) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - std::vector widgets; - if(v4d->hasNguiCtx()) { - for (auto* w : v4d->nguiCtx().screen().children()) { - auto pt = v4d->fbCtx().toWindowCoord(v4d->getMousePosition()); - auto mousePos = nanogui::Vector2i(pt[0] / v4d->pixelRatioX(), pt[1] / v4d->pixelRatioY()); - if(contains_absolute(w, mousePos)) { - v4d->nguiCtx().screen().scroll_callback_event(x, y); - return; - } - } - } -#ifndef __EMSCRIPTEN__ - v4d->zoom(y < 0 ? 1.1 : 0.9); -#endif - } - ); - - glfwSetWindowSizeCallback(getGLFWWindow(), - [](GLFWwindow* glfwWin, int width, int height) { - V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); - if(v4d->hasNguiCtx()) - v4d->nguiCtx().screen().resize_callback_event(width, height); - cv::Rect& vp = v4d->viewport(); - cv::Size fbsz = v4d->framebufferSize(); - vp.x = 0; - vp.y = 0; - vp.width = fbsz.width; - vp.height = fbsz.height; - }); - -// glfwSetFramebufferSizeCallback(getGLFWWindow(), -// [](GLFWwindow* glfwWin, int width, int height) { -// V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); -// cv::Rect& vp = v4d->viewport(); -// vp.x = 0; -// vp.y = 0; -// vp.width = width; -// vp.height = height; -//#ifndef __EMSCRIPTEN__ -// if(v4d->isResizable()) { -// v4d->nvgCtx().fbCtx().teardown(); -// v4d->glCtx().fbCtx().teardown(); -// v4d->fbCtx().teardown(); -// v4d->fbCtx().setup(cv::Size(width, height)); -// v4d->glCtx().fbCtx().setup(cv::Size(width, height)); -// v4d->nvgCtx().fbCtx().setup(cv::Size(width, height)); -// } -//#endif -// }); } int FrameBufferContext::getIndex() { diff --git a/modules/v4d/src/detail/framebuffercontext.hpp b/modules/v4d/src/detail/framebuffercontext.hpp index 2384eeb37..91584b46f 100644 --- a/modules/v4d/src/detail/framebuffercontext.hpp +++ b/modules/v4d/src/detail/framebuffercontext.hpp @@ -43,7 +43,6 @@ class FrameBufferContext { friend class NanoVGContext; friend class NanoguiContext; friend class cv::v4d::V4D; - V4D* v4d_ = nullptr; bool offscreen_; string title_; int major_; @@ -154,10 +153,10 @@ public: * Create a FrameBufferContext with given size. * @param frameBufferSize The frame buffer size. */ - FrameBufferContext(V4D& v4d, const cv::Size& frameBufferSize, bool offscreen, + FrameBufferContext(const cv::Size& frameBufferSize, bool offscreen, const string& title, int major, int minor, bool compat, int samples, bool debug, GLFWwindow* sharedWindow, const FrameBufferContext* parent); - FrameBufferContext(V4D& v4d, const string& title, const FrameBufferContext& other); + FrameBufferContext(const string& title, const FrameBufferContext& other); /*! * Default destructor. diff --git a/modules/v4d/src/detail/glcontext.cpp b/modules/v4d/src/detail/glcontext.cpp index 56666047d..91707c370 100644 --- a/modules/v4d/src/detail/glcontext.cpp +++ b/modules/v4d/src/detail/glcontext.cpp @@ -7,8 +7,8 @@ namespace cv { namespace v4d { namespace detail { -GLContext::GLContext(V4D& v4d, FrameBufferContext& fbContext) : - v4d_(v4d), mainFbContext_(fbContext), glFbContext_(v4d, "OpenGL", fbContext) { +GLContext::GLContext(FrameBufferContext& fbContext) : + mainFbContext_(fbContext), glFbContext_("OpenGL", fbContext) { run_sync_on_main<19>([&,this](){ #ifdef __EMSCRIPTEN__ mainFbContext_.initWebGLCopy(fbCtx()); diff --git a/modules/v4d/src/detail/glcontext.hpp b/modules/v4d/src/detail/glcontext.hpp index 5d5aaa048..a5f28bcfc 100644 --- a/modules/v4d/src/detail/glcontext.hpp +++ b/modules/v4d/src/detail/glcontext.hpp @@ -19,18 +19,14 @@ namespace detail { * Used to setup a nanovg context */ class GLContext { - V4D& v4d_; FrameBufferContext& mainFbContext_; FrameBufferContext glFbContext_; - cv::UMat preFB_; - cv::UMat fb_; - cv::UMat postFB_; public: /*! * Creates a OpenGL Context * @param fbContext The framebuffer context */ - GLContext(V4D& v4d, FrameBufferContext& fbContext); + GLContext(FrameBufferContext& fbContext); /*! * Execute function object fn inside a gl context. * The context takes care of setting up opengl states. diff --git a/modules/v4d/src/detail/nanoguicontext.cpp b/modules/v4d/src/detail/nanoguicontext.cpp index 052c5a669..673990921 100644 --- a/modules/v4d/src/detail/nanoguicontext.cpp +++ b/modules/v4d/src/detail/nanoguicontext.cpp @@ -10,8 +10,8 @@ namespace cv { namespace v4d { namespace detail { -NanoguiContext::NanoguiContext(V4D& v4d, FrameBufferContext& fbContext) : - NanoVGContext(v4d, fbContext) { +NanoguiContext::NanoguiContext(FrameBufferContext& fbContext) : + NanoVGContext(fbContext) { } void NanoguiContext::render() { diff --git a/modules/v4d/src/detail/nanoguicontext.hpp b/modules/v4d/src/detail/nanoguicontext.hpp index a11cc515d..2fdbe2b08 100644 --- a/modules/v4d/src/detail/nanoguicontext.hpp +++ b/modules/v4d/src/detail/nanoguicontext.hpp @@ -29,7 +29,7 @@ class NanoguiContext : public NanoVGContext { float fps_ = 0; bool first_ = true; public: - NanoguiContext(V4D& v4d, FrameBufferContext& fbContext); + NanoguiContext(FrameBufferContext& fbContext); void render(); void updateFps(bool print, bool graphical); void build(std::function fn); diff --git a/modules/v4d/src/detail/nanovgcontext.cpp b/modules/v4d/src/detail/nanovgcontext.cpp index 8377be920..7ee693fd2 100644 --- a/modules/v4d/src/detail/nanovgcontext.cpp +++ b/modules/v4d/src/detail/nanovgcontext.cpp @@ -10,8 +10,8 @@ namespace cv { namespace v4d { namespace detail { -NanoVGContext::NanoVGContext(V4D& v4d, FrameBufferContext& fbContext) : - v4d_(v4d), mainFbContext_(fbContext), nvgFbContext_(v4d, "NanoVG", fbContext), context_( +NanoVGContext::NanoVGContext(FrameBufferContext& fbContext) : + mainFbContext_(fbContext), nvgFbContext_("NanoVG", fbContext), context_( nullptr) { UMat tmp(fbCtx().size(), CV_8UC4); diff --git a/modules/v4d/src/detail/nanovgcontext.hpp b/modules/v4d/src/detail/nanovgcontext.hpp index 88b200877..df9c2dbaf 100644 --- a/modules/v4d/src/detail/nanovgcontext.hpp +++ b/modules/v4d/src/detail/nanovgcontext.hpp @@ -25,7 +25,6 @@ namespace detail { * Used to setup a nanovg context */ class NanoVGContext { - V4D& v4d_; protected: nanogui::Screen* screen_; cv::v4d::FormHelper* form_; @@ -61,7 +60,7 @@ public: * @param context The native NVGContext * @param fbContext The framebuffer context */ - NanoVGContext(V4D& v4d, FrameBufferContext& fbContext); + NanoVGContext(FrameBufferContext& fbContext); /*! * Execute function object fn inside a nanovg context. diff --git a/modules/v4d/src/v4d.cpp b/modules/v4d/src/v4d.cpp index 976599fcc..a5594b294 100644 --- a/modules/v4d/src/v4d.cpp +++ b/modules/v4d/src/v4d.cpp @@ -17,6 +17,11 @@ namespace cv { namespace v4d { namespace detail { +static bool contains_absolute(nanogui::Widget* w, const nanogui::Vector2i& p) { + nanogui::Vector2i d = p - w->absolute_position(); + return d.x() >= 0 && d.y() >= 0 && d.x() < w->size().x() && d.y() < w->size().y(); +} + void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error: (%d) %s\n", error, description); } @@ -49,13 +54,114 @@ V4D::V4D(const cv::Size& size, const cv::Size& fbsize, const string& title, bool #ifdef __EMSCRIPTEN__ printf(""); //makes sure we have FS as a dependency #endif - mainFbContext_ = new detail::FrameBufferContext(*this, fbsize.empty() ? size : fbsize, offscreen, title_, major_, + mainFbContext_ = new detail::FrameBufferContext(fbsize.empty() ? size : fbsize, offscreen, title_, major_, minor_, compat_, samples_, debug_, nullptr, nullptr); - nvgContext_ = new detail::NanoVGContext(*this, *mainFbContext_); - nguiContext_ = new detail::NanoguiContext(*this, *mainFbContext_); - clvaContext_ = new detail::CLVAContext(*this, *mainFbContext_); - glContext_ = new detail::GLContext(*this, *mainFbContext_); + nvgContext_ = new detail::NanoVGContext(*mainFbContext_); + nguiContext_ = new detail::NanoguiContext(*mainFbContext_); + clvaContext_ = new detail::CLVAContext(*mainFbContext_); + glContext_ = new detail::GLContext(*mainFbContext_); + + glfwSetWindowUserPointer(getGLFWWindow(), this); + + glfwSetCursorPosCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, double x, double y) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) { + auto pt = v4d->fbCtx().toWindowCoord(cv::Point2f(x, y)); + v4d->nguiCtx().screen().cursor_pos_callback_event(pt.x, pt.y); + } + #ifndef __EMSCRIPTEN__ + auto cursor = v4d->getMousePosition(); + auto diff = cursor - cv::Vec2f(x, y); + if (v4d->isMouseDrag()) { + v4d->pan(diff[0], -diff[1]); + } + #endif + v4d->setMousePosition(x, y); + } + ); + glfwSetMouseButtonCallback(getGLFWWindow(), + [](GLFWwindow* glfwWin, int button, int action, int modifiers) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) + v4d->nguiCtx().screen().mouse_button_callback_event(button, action, modifiers); + if (button == GLFW_MOUSE_BUTTON_RIGHT) { + v4d->setMouseDrag(action == GLFW_PRESS); + } + } + ); + glfwSetKeyCallback(getGLFWWindow(), + [](GLFWwindow* glfwWin, int key, int scancode, int action, int mods) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) + v4d->nguiCtx().screen().key_callback_event(key, scancode, action, mods); + } + ); + glfwSetCharCallback(getGLFWWindow(), [](GLFWwindow* glfwWin, unsigned int codepoint) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) + v4d->nguiCtx().screen().char_callback_event(codepoint); + } + ); + glfwSetDropCallback(getGLFWWindow(), + [](GLFWwindow* glfwWin, int count, const char** filenames) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) + v4d->nguiCtx().screen().drop_callback_event(count, filenames); + } + ); + glfwSetScrollCallback(getGLFWWindow(), + [](GLFWwindow* glfwWin, double x, double y) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + std::vector widgets; + if(v4d->hasNguiCtx()) { + for (auto* w : v4d->nguiCtx().screen().children()) { + auto pt = v4d->fbCtx().toWindowCoord(v4d->getMousePosition()); + auto mousePos = nanogui::Vector2i(pt[0] / v4d->pixelRatioX(), pt[1] / v4d->pixelRatioY()); + if(cv::v4d::detail::contains_absolute(w, mousePos)) { + v4d->nguiCtx().screen().scroll_callback_event(x, y); + return; + } + } + } + #ifndef __EMSCRIPTEN__ + v4d->zoom(y < 0 ? 1.1 : 0.9); + #endif + } + ); + + glfwSetWindowSizeCallback(getGLFWWindow(), + [](GLFWwindow* glfwWin, int width, int height) { + V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + if(v4d->hasNguiCtx()) + v4d->nguiCtx().screen().resize_callback_event(width, height); + cv::Rect& vp = v4d->viewport(); + cv::Size fbsz = v4d->framebufferSize(); + vp.x = 0; + vp.y = 0; + vp.width = fbsz.width; + vp.height = fbsz.height; + }); + + // glfwSetFramebufferSizeCallback(getGLFWWindow(), + // [](GLFWwindow* glfwWin, int width, int height) { + // V4D* v4d = reinterpret_cast(glfwGetWindowUserPointer(glfwWin)); + // cv::Rect& vp = v4d->viewport(); + // vp.x = 0; + // vp.y = 0; + // vp.width = width; + // vp.height = height; + //#ifndef __EMSCRIPTEN__ + // if(v4d->isResizable()) { + // v4d->nvgCtx().fbCtx().teardown(); + // v4d->glCtx().fbCtx().teardown(); + // v4d->fbCtx().teardown(); + // v4d->fbCtx().setup(cv::Size(width, height)); + // v4d->glCtx().fbCtx().setup(cv::Size(width, height)); + // v4d->nvgCtx().fbCtx().setup(cv::Size(width, height)); + // } + //#endif + // }); } V4D::~V4D() { @@ -183,6 +289,7 @@ static void do_frame(void* void_fn_ptr) { auto* fn_ptr = reinterpret_cast*>(void_fn_ptr); if (fn_ptr) { auto& fn = *fn_ptr; + //FIXME cancel main loop fn(); } }