From 7911a22cc53d43501b3c36a2f8b8fd0398020287 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 9 Feb 2017 03:56:17 -0500 Subject: [PATCH] Added wire snapping --- Makefile | 2 +- include/scene.hpp | 6 ++++++ include/widgets.hpp | 3 +++ src/gui.cpp | 37 ++++++++++++++++++++++--------------- src/widgets.cpp | 1 + src/widgets/InputPort.cpp | 13 +++++++++++++ src/widgets/Light.cpp | 9 ++++----- src/widgets/OutputPort.cpp | 13 +++++++++++++ src/widgets/Port.cpp | 1 - src/widgets/RadioButton.cpp | 2 ++ src/widgets/Widget.cpp | 12 +++++------- src/widgets/WireWidget.cpp | 30 +++++++++++++++++++++--------- 12 files changed, 91 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 980ce553..795e7390 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ LDFLAGS += \ -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows TARGET = Rack.exe -# OBJECTS = Rack.res +OBJECTS = Rack.res %.res: %.rc windres $^ -O coff -o $@ diff --git a/include/scene.hpp b/include/scene.hpp index c34b8aab..8373f4a8 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -59,6 +59,8 @@ struct ModuleWidget : OpaqueWidget { struct WireWidget : OpaqueWidget { OutputPort *outputPort = NULL; InputPort *inputPort = NULL; + OutputPort *hoveredOutputPort = NULL; + InputPort *hoveredInputPort = NULL; Wire *wire = NULL; NVGcolor color; @@ -183,6 +185,8 @@ struct InputPort : Port { void onDragStart(); void onDragDrop(Widget *origin); + void onDragEnter(Widget *origin); + void onDragLeave(Widget *origin); }; struct OutputPort : Port { @@ -190,6 +194,8 @@ struct OutputPort : Port { void onDragStart(); void onDragDrop(Widget *origin); + void onDragEnter(Widget *origin); + void onDragLeave(Widget *origin); }; //////////////////// diff --git a/include/widgets.hpp b/include/widgets.hpp index 31a1c237..cb05b574 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -104,6 +104,8 @@ struct Widget { /** Called when a widget responds to `onMouseMove` and is being dragged */ virtual void onDragMove(Vec mouseRel) {} /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */ + virtual void onDragEnter(Widget *origin) {} + virtual void onDragLeave(Widget *origin) {} virtual void onDragDrop(Widget *origin) {} virtual void onAction() {} @@ -318,6 +320,7 @@ struct Scene : OpaqueWidget { extern Vec gMousePos; extern Widget *gHoveredWidget; extern Widget *gDraggedWidget; +extern Widget *gDragHoveredWidget; extern Widget *gSelectedWidget; extern int gGuiFrame; diff --git a/src/gui.cpp b/src/gui.cpp index f5106603..f4540ef8 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -60,6 +60,7 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { gDraggedWidget->onDragEnd(); } gDraggedWidget = NULL; + gDragHoveredWidget = NULL; } } } @@ -69,27 +70,33 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { Vec mouseRel = mousePos.minus(gMousePos); gMousePos = mousePos; - if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) { - // TODO Lock gMousePos - } + bool locked = glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; - // onScroll - // int middleButton = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE); - // if (middleButton == GLFW_PRESS) { - // gScene->scrollWidget->onScroll(mouseRel.neg()); - // } + // onMouseMove + Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel); if (gDraggedWidget) { // onDragMove // Drag slower if Ctrl is held - bool fine = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; - float factor = fine ? 1.0/8.0 : 1.0; - gDraggedWidget->onDragMove(mouseRel.mult(factor)); + if (locked) { + bool ctrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; + if (ctrl) + mouseRel = mouseRel.mult(0.1); + } + gDraggedWidget->onDragMove(mouseRel); + + if (hovered != gDragHoveredWidget) { + if (gDragHoveredWidget) { + gDragHoveredWidget->onDragLeave(gDraggedWidget); + } + if (hovered) { + hovered->onDragEnter(gDraggedWidget); + } + gDragHoveredWidget = hovered; + } + } else { - // onMouseMove - Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel); - if (hovered != gHoveredWidget) { if (gHoveredWidget) { // onMouseLeave @@ -99,8 +106,8 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { // onMouseEnter hovered->onMouseEnter(); } + gHoveredWidget = hovered; } - gHoveredWidget = hovered; } } diff --git a/src/widgets.cpp b/src/widgets.cpp index 09a54ec1..912700cb 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -5,6 +5,7 @@ namespace rack { Vec gMousePos; Widget *gHoveredWidget = NULL; Widget *gDraggedWidget = NULL; +Widget *gDragHoveredWidget = NULL; Widget *gSelectedWidget = NULL; int gGuiFrame; diff --git a/src/widgets/InputPort.cpp b/src/widgets/InputPort.cpp index 27f5b62e..206abeb0 100644 --- a/src/widgets/InputPort.cpp +++ b/src/widgets/InputPort.cpp @@ -22,11 +22,24 @@ void InputPort::onDragStart() { void InputPort::onDragDrop(Widget *origin) { if (connectedWire) return; if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredInputPort = NULL; if (gRackWidget->activeWire->inputPort) return; gRackWidget->activeWire->inputPort = this; connectedWire = gRackWidget->activeWire; } } +void InputPort::onDragEnter(Widget *origin) { + if (connectedWire) return; + if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredInputPort = this; + } +} + +void InputPort::onDragLeave(Widget *origin) { + if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredInputPort = NULL; + } +} } // namespace rack diff --git a/src/widgets/Light.cpp b/src/widgets/Light.cpp index 537f14ca..19cc8a70 100644 --- a/src/widgets/Light.cpp +++ b/src/widgets/Light.cpp @@ -9,16 +9,15 @@ void Light::draw(NVGcontext *vg) { Vec c = box.getCenter(); Vec r = box.size.div(2.0); - nvgBeginPath(vg); - nvgEllipse(vg, c.x, c.y, r.x, r.y); - nvgFillColor(vg, colorOutline); - nvgFill(vg); - nvgBeginPath(vg); nvgEllipse(vg, c.x, c.y, r.x - 1.0, r.y - 1.0); nvgFillColor(vg, color); nvgFill(vg); + nvgStrokeWidth(vg, 1.0); + nvgStrokeColor(vg, colorOutline); + nvgStroke(vg); + // float radius = box.size.x / 2.0; // NVGcolor icol, ocol; // NVGpaint paint; diff --git a/src/widgets/OutputPort.cpp b/src/widgets/OutputPort.cpp index 32348d14..f34c611d 100644 --- a/src/widgets/OutputPort.cpp +++ b/src/widgets/OutputPort.cpp @@ -22,11 +22,24 @@ void OutputPort::onDragStart() { void OutputPort::onDragDrop(Widget *origin) { if (connectedWire) return; if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredOutputPort = NULL; if (gRackWidget->activeWire->outputPort) return; gRackWidget->activeWire->outputPort = this; connectedWire = gRackWidget->activeWire; } } +void OutputPort::onDragEnter(Widget *origin) { + if (connectedWire) return; + if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredOutputPort = this; + } +} + +void OutputPort::onDragLeave(Widget *origin) { + if (gRackWidget->activeWire) { + gRackWidget->activeWire->hoveredOutputPort = NULL; + } +} } // namespace rack diff --git a/src/widgets/Port.cpp b/src/widgets/Port.cpp index 0686871b..bdfda165 100644 --- a/src/widgets/Port.cpp +++ b/src/widgets/Port.cpp @@ -36,5 +36,4 @@ void Port::onDragEnd() { gRackWidget->activeWire = NULL; } - } // namespace rack diff --git a/src/widgets/RadioButton.cpp b/src/widgets/RadioButton.cpp index fe8a6540..8f5468eb 100644 --- a/src/widgets/RadioButton.cpp +++ b/src/widgets/RadioButton.cpp @@ -21,6 +21,8 @@ void RadioButton::onDragDrop(Widget *origin) { value = 1.0; else value = 0.0; + + onAction(); } } diff --git a/src/widgets/Widget.cpp b/src/widgets/Widget.cpp index 280537e9..78116dad 100644 --- a/src/widgets/Widget.cpp +++ b/src/widgets/Widget.cpp @@ -8,12 +8,10 @@ Widget::~Widget() { // You should only delete orphaned widgets assert(!parent); // Stop dragging and hovering this widget - if (gHoveredWidget == this) - gHoveredWidget = NULL; - if (gDraggedWidget == this) - gDraggedWidget = NULL; - if (gSelectedWidget == this) - gSelectedWidget = NULL; + if (gHoveredWidget == this) gHoveredWidget = NULL; + if (gDraggedWidget == this) gDraggedWidget = NULL; + if (gDragHoveredWidget == this) gDragHoveredWidget = NULL; + if (gSelectedWidget == this) gSelectedWidget = NULL; clearChildren(); } @@ -71,9 +69,9 @@ void Widget::step() { } void Widget::draw(NVGcontext *vg) { - nvgSave(vg); nvgTranslate(vg, box.pos.x, box.pos.y); for (Widget *child : children) { + nvgSave(vg); child->draw(vg); } nvgRestore(vg); diff --git a/src/widgets/WireWidget.cpp b/src/widgets/WireWidget.cpp index e635136a..52e67f52 100644 --- a/src/widgets/WireWidget.cpp +++ b/src/widgets/WireWidget.cpp @@ -7,16 +7,18 @@ namespace rack { static void drawPlug(NVGcontext *vg, Vec pos, NVGcolor color) { NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); - nvgBeginPath(vg); - nvgCircle(vg, pos.x, pos.y, 10.5); - nvgFillColor(vg, colorOutline); - nvgFill(vg); - + // Plug solid nvgBeginPath(vg); nvgCircle(vg, pos.x, pos.y, 9.5); nvgFillColor(vg, color); nvgFill(vg); + // Border + nvgStrokeWidth(vg, 1.0); + nvgStrokeColor(vg, colorOutline); + nvgStroke(vg); + + // Hole nvgBeginPath(vg); nvgCircle(vg, pos.x, pos.y, 5.5); nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); @@ -118,25 +120,35 @@ void WireWidget::updateWire() { } void WireWidget::draw(NVGcontext *vg) { - Vec outputPos, inputPos; Vec absolutePos = getAbsolutePos(); float opacity = dynamic_cast(gScene)->toolbar->wireOpacitySlider->value / 100.0; float tension = dynamic_cast(gScene)->toolbar->wireTensionSlider->value; - // Compute location of pos1 and pos2 + // Display the actively dragged wire as opaque + if (gRackWidget->activeWire == this) + opacity = 1.0; + + // Compute location of outputPos and inputPos + Vec outputPos; if (outputPort) { outputPos = Rect(outputPort->getAbsolutePos(), outputPort->box.size).getCenter(); } + else if (hoveredOutputPort) { + outputPos = Rect(hoveredOutputPort->getAbsolutePos(), hoveredOutputPort->box.size).getCenter(); + } else { outputPos = gMousePos; - opacity = 1.0; } + + Vec inputPos; if (inputPort) { inputPos = Rect(inputPort->getAbsolutePos(), inputPort->box.size).getCenter(); } + else if (hoveredInputPort) { + inputPos = Rect(hoveredInputPort->getAbsolutePos(), hoveredInputPort->box.size).getCenter(); + } else { inputPos = gMousePos; - opacity = 1.0; } outputPos = outputPos.minus(absolutePos);