| @@ -11,6 +11,9 @@ namespace app { | |||||
| struct Scene : widget::OpaqueWidget { | struct Scene : widget::OpaqueWidget { | ||||
| struct Internal; | |||||
| Internal* internal; | |||||
| // Convenience variables for accessing important widgets | // Convenience variables for accessing important widgets | ||||
| RackScrollWidget* rackScroll; | RackScrollWidget* rackScroll; | ||||
| RackWidget* rack; | RackWidget* rack; | ||||
| @@ -19,16 +22,15 @@ struct Scene : widget::OpaqueWidget { | |||||
| widget::Widget* frameRateWidget; | widget::Widget* frameRateWidget; | ||||
| double lastAutosaveTime = 0.0; | double lastAutosaveTime = 0.0; | ||||
| // Version checking | |||||
| bool checkVersion = true; | |||||
| bool checkedVersion = false; | |||||
| std::string latestVersion; | |||||
| /** The last mouse position in the Scene */ | |||||
| math::Vec mousePos; | |||||
| Scene(); | Scene(); | ||||
| ~Scene(); | ~Scene(); | ||||
| void step() override; | void step() override; | ||||
| void draw(const DrawArgs& args) override; | void draw(const DrawArgs& args) override; | ||||
| void onHover(const event::Hover& e) override; | |||||
| void onDragHover(const event::DragHover& e) override; | |||||
| void onHoverKey(const event::HoverKey& e) override; | void onHoverKey(const event::HoverKey& e) override; | ||||
| void onPathDrop(const event::PathDrop& e) override; | void onPathDrop(const event::PathDrop& e) override; | ||||
| @@ -11,7 +11,6 @@ | |||||
| #include <engine/Module.hpp> | #include <engine/Module.hpp> | ||||
| #include <engine/ParamQuantity.hpp> | #include <engine/ParamQuantity.hpp> | ||||
| #include <app.hpp> | #include <app.hpp> | ||||
| #include <window.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -156,7 +155,7 @@ TMenuItem * createMenuItem(std::string text, std::string rightText = "") { | |||||
| template <class TMenu = ui::Menu> | template <class TMenu = ui::Menu> | ||||
| TMenu * createMenu() { | TMenu * createMenu() { | ||||
| TMenu* o = new TMenu; | TMenu* o = new TMenu; | ||||
| o->box.pos = APP->window->mousePos; | |||||
| o->box.pos = APP->scene->mousePos; | |||||
| ui::MenuOverlay* menuOverlay = new ui::MenuOverlay; | ui::MenuOverlay* menuOverlay = new ui::MenuOverlay; | ||||
| menuOverlay->addChild(o); | menuOverlay->addChild(o); | ||||
| @@ -53,6 +53,9 @@ DEPRECATED typedef Svg SVG; | |||||
| struct Window { | struct Window { | ||||
| struct Internal; | |||||
| Internal* internal; | |||||
| GLFWwindow* win = NULL; | GLFWwindow* win = NULL; | ||||
| NVGcontext* vg = NULL; | NVGcontext* vg = NULL; | ||||
| /** The scaling ratio */ | /** The scaling ratio */ | ||||
| @@ -62,8 +65,6 @@ struct Window { | |||||
| */ | */ | ||||
| float windowRatio = 1.f; | float windowRatio = 1.f; | ||||
| int frame = 0; | int frame = 0; | ||||
| /** The last known absolute mouse position in the window */ | |||||
| math::Vec mousePos; | |||||
| std::shared_ptr<Font> uiFont; | std::shared_ptr<Font> uiFont; | ||||
| double frameTimeStart = 0.f; | double frameTimeStart = 0.f; | ||||
| @@ -72,9 +73,6 @@ struct Window { | |||||
| std::map<std::string, std::weak_ptr<Image>> imageCache; | std::map<std::string, std::weak_ptr<Image>> imageCache; | ||||
| std::map<std::string, std::weak_ptr<Svg>> svgCache; | std::map<std::string, std::weak_ptr<Svg>> svgCache; | ||||
| struct Internal; | |||||
| Internal* internal; | |||||
| Window(); | Window(); | ||||
| ~Window(); | ~Window(); | ||||
| void run(); | void run(); | ||||
| @@ -56,7 +56,7 @@ void RackScrollWidget::step() { | |||||
| rackWidget->box.pos = scrollBox.pos.div(zoom).neg(); | rackWidget->box.pos = scrollBox.pos.div(zoom).neg(); | ||||
| // Scroll rack if dragging cable near the edge of the screen | // Scroll rack if dragging cable near the edge of the screen | ||||
| math::Vec pos = APP->window->mousePos; | |||||
| math::Vec pos = APP->scene->mousePos; | |||||
| math::Rect viewport = getViewport(box.zeroPos()); | math::Rect viewport = getViewport(box.zeroPos()); | ||||
| if (rackWidget->incompleteCable) { | if (rackWidget->incompleteCable) { | ||||
| float margin = 20.0; | float margin = 20.0; | ||||
| @@ -15,6 +15,10 @@ namespace rack { | |||||
| namespace app { | namespace app { | ||||
| struct Scene::Internal { | |||||
| }; | |||||
| struct FrameRateWidget : widget::TransparentWidget { | struct FrameRateWidget : widget::TransparentWidget { | ||||
| void draw(const DrawArgs& args) override { | void draw(const DrawArgs& args) override { | ||||
| std::string text = string::f("%.2f Hz", APP->window->getLastFrameRate()); | std::string text = string::f("%.2f Hz", APP->window->getLastFrameRate()); | ||||
| @@ -24,6 +28,8 @@ struct FrameRateWidget : widget::TransparentWidget { | |||||
| Scene::Scene() { | Scene::Scene() { | ||||
| internal = new Internal; | |||||
| rackScroll = new RackScrollWidget; | rackScroll = new RackScrollWidget; | ||||
| addChild(rackScroll); | addChild(rackScroll); | ||||
| @@ -43,6 +49,7 @@ Scene::Scene() { | |||||
| } | } | ||||
| Scene::~Scene() { | Scene::~Scene() { | ||||
| delete internal; | |||||
| } | } | ||||
| void Scene::step() { | void Scene::step() { | ||||
| @@ -72,6 +79,16 @@ void Scene::draw(const DrawArgs& args) { | |||||
| Widget::draw(args); | Widget::draw(args); | ||||
| } | } | ||||
| void Scene::onHover(const event::Hover& e) { | |||||
| mousePos = e.pos; | |||||
| OpaqueWidget::onHover(e); | |||||
| } | |||||
| void Scene::onDragHover(const event::DragHover& e) { | |||||
| mousePos = e.pos; | |||||
| OpaqueWidget::onDragHover(e); | |||||
| } | |||||
| void Scene::onHoverKey(const event::HoverKey& e) { | void Scene::onHoverKey(const event::HoverKey& e) { | ||||
| OpaqueWidget::onHoverKey(e); | OpaqueWidget::onHoverKey(e); | ||||
| if (e.isConsumed()) | if (e.isConsumed()) | ||||
| @@ -1,6 +1,6 @@ | |||||
| #include <ui/Tooltip.hpp> | #include <ui/Tooltip.hpp> | ||||
| #include <app.hpp> | #include <app.hpp> | ||||
| #include <window.hpp> | |||||
| #include <app/Scene.hpp> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -12,7 +12,7 @@ void Tooltip::step() { | |||||
| box.size.x = bndLabelWidth(APP->window->vg, -1, text.c_str()) + 10.0; | box.size.x = bndLabelWidth(APP->window->vg, -1, text.c_str()) + 10.0; | ||||
| box.size.y = bndLabelHeight(APP->window->vg, -1, text.c_str(), INFINITY); | box.size.y = bndLabelHeight(APP->window->vg, -1, text.c_str(), INFINITY); | ||||
| // Position near cursor. This assumes that `this` is added to the root widget. | // Position near cursor. This assumes that `this` is added to the root widget. | ||||
| box.pos = APP->window->mousePos.plus(math::Vec(15, 15)); | |||||
| box.pos = APP->scene->mousePos.plus(math::Vec(15, 15)); | |||||
| // Fit inside parent | // Fit inside parent | ||||
| assert(parent); | assert(parent); | ||||
| box = box.nudge(parent->box.zeroPos()); | box = box.nudge(parent->box.zeroPos()); | ||||
| @@ -98,6 +98,8 @@ struct Window::Internal { | |||||
| int frameSwapInterval = -1; | int frameSwapInterval = -1; | ||||
| float monitorRefreshRate = 0.f; | float monitorRefreshRate = 0.f; | ||||
| float lastFrameRate = 0.f; | float lastFrameRate = 0.f; | ||||
| math::Vec lastMousePos; | |||||
| }; | }; | ||||
| @@ -120,13 +122,13 @@ static void mouseButtonCallback(GLFWwindow* win, int button, int action, int mod | |||||
| } | } | ||||
| #endif | #endif | ||||
| APP->event->handleButton(window->mousePos, button, action, mods); | |||||
| APP->event->handleButton(window->internal->lastMousePos, button, action, mods); | |||||
| } | } | ||||
| static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { | static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { | ||||
| Window* window = (Window*) glfwGetWindowUserPointer(win); | Window* window = (Window*) glfwGetWindowUserPointer(win); | ||||
| math::Vec mousePos = math::Vec(xpos, ypos).div(window->pixelRatio / window->windowRatio).round(); | math::Vec mousePos = math::Vec(xpos, ypos).div(window->pixelRatio / window->windowRatio).round(); | ||||
| math::Vec mouseDelta = mousePos.minus(window->mousePos); | |||||
| math::Vec mouseDelta = mousePos.minus(window->internal->lastMousePos); | |||||
| // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. | // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. | ||||
| if (window->internal->ignoreNextMouseDelta) { | if (window->internal->ignoreNextMouseDelta) { | ||||
| @@ -142,15 +144,15 @@ static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { | |||||
| // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. | // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. | ||||
| if (cursorMode == GLFW_CURSOR_HIDDEN) { | if (cursorMode == GLFW_CURSOR_HIDDEN) { | ||||
| // CGSetLocalEventsSuppressionInterval(0.0); | // CGSetLocalEventsSuppressionInterval(0.0); | ||||
| glfwSetCursorPos(win, window->mousePos.x, window->mousePos.y); | |||||
| glfwSetCursorPos(win, window->internal->lastMousePos.x, window->internal->lastMousePos.y); | |||||
| CGAssociateMouseAndMouseCursorPosition(true); | CGAssociateMouseAndMouseCursorPosition(true); | ||||
| mousePos = window->mousePos; | |||||
| mousePos = window->internal->lastMousePos; | |||||
| } | } | ||||
| // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window | // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window | ||||
| glfwSetCursor(win, NULL); | glfwSetCursor(win, NULL); | ||||
| #endif | #endif | ||||
| window->mousePos = mousePos; | |||||
| window->internal->lastMousePos = mousePos; | |||||
| APP->event->handleHover(mousePos, mouseDelta); | APP->event->handleHover(mousePos, mouseDelta); | ||||
| } | } | ||||
| @@ -170,18 +172,18 @@ static void scrollCallback(GLFWwindow* win, double x, double y) { | |||||
| scrollDelta = scrollDelta.mult(50.0); | scrollDelta = scrollDelta.mult(50.0); | ||||
| #endif | #endif | ||||
| APP->event->handleScroll(window->mousePos, scrollDelta); | |||||
| APP->event->handleScroll(window->internal->lastMousePos, scrollDelta); | |||||
| } | } | ||||
| static void charCallback(GLFWwindow* win, unsigned int codepoint) { | static void charCallback(GLFWwindow* win, unsigned int codepoint) { | ||||
| Window* window = (Window*) glfwGetWindowUserPointer(win); | Window* window = (Window*) glfwGetWindowUserPointer(win); | ||||
| if (APP->event->handleText(window->mousePos, codepoint)) | |||||
| if (APP->event->handleText(window->internal->lastMousePos, codepoint)) | |||||
| return; | return; | ||||
| } | } | ||||
| static void keyCallback(GLFWwindow* win, int key, int scancode, int action, int mods) { | static void keyCallback(GLFWwindow* win, int key, int scancode, int action, int mods) { | ||||
| Window* window = (Window*) glfwGetWindowUserPointer(win); | Window* window = (Window*) glfwGetWindowUserPointer(win); | ||||
| if (APP->event->handleKey(window->mousePos, key, scancode, action, mods)) | |||||
| if (APP->event->handleKey(window->internal->lastMousePos, key, scancode, action, mods)) | |||||
| return; | return; | ||||
| // Keyboard MIDI driver | // Keyboard MIDI driver | ||||
| @@ -199,7 +201,7 @@ static void dropCallback(GLFWwindow* win, int count, const char** paths) { | |||||
| for (int i = 0; i < count; i++) { | for (int i = 0; i < count; i++) { | ||||
| pathsVec.push_back(paths[i]); | pathsVec.push_back(paths[i]); | ||||
| } | } | ||||
| APP->event->handleDrop(window->mousePos, pathsVec); | |||||
| APP->event->handleDrop(window->internal->lastMousePos, pathsVec); | |||||
| } | } | ||||
| static void errorCallback(int error, const char* description) { | static void errorCallback(int error, const char* description) { | ||||