@@ -11,6 +11,9 @@ namespace app { | |||
struct Scene : widget::OpaqueWidget { | |||
struct Internal; | |||
Internal* internal; | |||
// Convenience variables for accessing important widgets | |||
RackScrollWidget* rackScroll; | |||
RackWidget* rack; | |||
@@ -19,16 +22,15 @@ struct Scene : widget::OpaqueWidget { | |||
widget::Widget* frameRateWidget; | |||
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(); | |||
void step() 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 onPathDrop(const event::PathDrop& e) override; | |||
@@ -11,7 +11,6 @@ | |||
#include <engine/Module.hpp> | |||
#include <engine/ParamQuantity.hpp> | |||
#include <app.hpp> | |||
#include <window.hpp> | |||
namespace rack { | |||
@@ -156,7 +155,7 @@ TMenuItem * createMenuItem(std::string text, std::string rightText = "") { | |||
template <class TMenu = ui::Menu> | |||
TMenu * createMenu() { | |||
TMenu* o = new TMenu; | |||
o->box.pos = APP->window->mousePos; | |||
o->box.pos = APP->scene->mousePos; | |||
ui::MenuOverlay* menuOverlay = new ui::MenuOverlay; | |||
menuOverlay->addChild(o); | |||
@@ -53,6 +53,9 @@ DEPRECATED typedef Svg SVG; | |||
struct Window { | |||
struct Internal; | |||
Internal* internal; | |||
GLFWwindow* win = NULL; | |||
NVGcontext* vg = NULL; | |||
/** The scaling ratio */ | |||
@@ -62,8 +65,6 @@ struct Window { | |||
*/ | |||
float windowRatio = 1.f; | |||
int frame = 0; | |||
/** The last known absolute mouse position in the window */ | |||
math::Vec mousePos; | |||
std::shared_ptr<Font> uiFont; | |||
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<Svg>> svgCache; | |||
struct Internal; | |||
Internal* internal; | |||
Window(); | |||
~Window(); | |||
void run(); | |||
@@ -56,7 +56,7 @@ void RackScrollWidget::step() { | |||
rackWidget->box.pos = scrollBox.pos.div(zoom).neg(); | |||
// 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()); | |||
if (rackWidget->incompleteCable) { | |||
float margin = 20.0; | |||
@@ -15,6 +15,10 @@ namespace rack { | |||
namespace app { | |||
struct Scene::Internal { | |||
}; | |||
struct FrameRateWidget : widget::TransparentWidget { | |||
void draw(const DrawArgs& args) override { | |||
std::string text = string::f("%.2f Hz", APP->window->getLastFrameRate()); | |||
@@ -24,6 +28,8 @@ struct FrameRateWidget : widget::TransparentWidget { | |||
Scene::Scene() { | |||
internal = new Internal; | |||
rackScroll = new RackScrollWidget; | |||
addChild(rackScroll); | |||
@@ -43,6 +49,7 @@ Scene::Scene() { | |||
} | |||
Scene::~Scene() { | |||
delete internal; | |||
} | |||
void Scene::step() { | |||
@@ -72,6 +79,16 @@ void Scene::draw(const DrawArgs& 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) { | |||
OpaqueWidget::onHoverKey(e); | |||
if (e.isConsumed()) | |||
@@ -1,6 +1,6 @@ | |||
#include <ui/Tooltip.hpp> | |||
#include <app.hpp> | |||
#include <window.hpp> | |||
#include <app/Scene.hpp> | |||
namespace rack { | |||
@@ -12,7 +12,7 @@ void Tooltip::step() { | |||
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); | |||
// 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 | |||
assert(parent); | |||
box = box.nudge(parent->box.zeroPos()); | |||
@@ -98,6 +98,8 @@ struct Window::Internal { | |||
int frameSwapInterval = -1; | |||
float monitorRefreshRate = 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 | |||
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) { | |||
Window* window = (Window*) glfwGetWindowUserPointer(win); | |||
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. | |||
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. | |||
if (cursorMode == GLFW_CURSOR_HIDDEN) { | |||
// CGSetLocalEventsSuppressionInterval(0.0); | |||
glfwSetCursorPos(win, window->mousePos.x, window->mousePos.y); | |||
glfwSetCursorPos(win, window->internal->lastMousePos.x, window->internal->lastMousePos.y); | |||
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 | |||
glfwSetCursor(win, NULL); | |||
#endif | |||
window->mousePos = mousePos; | |||
window->internal->lastMousePos = mousePos; | |||
APP->event->handleHover(mousePos, mouseDelta); | |||
} | |||
@@ -170,18 +172,18 @@ static void scrollCallback(GLFWwindow* win, double x, double y) { | |||
scrollDelta = scrollDelta.mult(50.0); | |||
#endif | |||
APP->event->handleScroll(window->mousePos, scrollDelta); | |||
APP->event->handleScroll(window->internal->lastMousePos, scrollDelta); | |||
} | |||
static void charCallback(GLFWwindow* win, unsigned int codepoint) { | |||
Window* window = (Window*) glfwGetWindowUserPointer(win); | |||
if (APP->event->handleText(window->mousePos, codepoint)) | |||
if (APP->event->handleText(window->internal->lastMousePos, codepoint)) | |||
return; | |||
} | |||
static void keyCallback(GLFWwindow* win, int key, int scancode, int action, int mods) { | |||
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; | |||
// Keyboard MIDI driver | |||
@@ -199,7 +201,7 @@ static void dropCallback(GLFWwindow* win, int count, const char** paths) { | |||
for (int i = 0; i < count; 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) { | |||