@@ -38,7 +38,7 @@ LDFLAGS += \ | |||||
-L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | ||||
-Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | ||||
TARGET = Rack.exe | TARGET = Rack.exe | ||||
# OBJECTS = Rack.res | |||||
OBJECTS = Rack.res | |||||
%.res: %.rc | %.res: %.rc | ||||
windres $^ -O coff -o $@ | windres $^ -O coff -o $@ | ||||
@@ -59,6 +59,8 @@ struct ModuleWidget : OpaqueWidget { | |||||
struct WireWidget : OpaqueWidget { | struct WireWidget : OpaqueWidget { | ||||
OutputPort *outputPort = NULL; | OutputPort *outputPort = NULL; | ||||
InputPort *inputPort = NULL; | InputPort *inputPort = NULL; | ||||
OutputPort *hoveredOutputPort = NULL; | |||||
InputPort *hoveredInputPort = NULL; | |||||
Wire *wire = NULL; | Wire *wire = NULL; | ||||
NVGcolor color; | NVGcolor color; | ||||
@@ -183,6 +185,8 @@ struct InputPort : Port { | |||||
void onDragStart(); | void onDragStart(); | ||||
void onDragDrop(Widget *origin); | void onDragDrop(Widget *origin); | ||||
void onDragEnter(Widget *origin); | |||||
void onDragLeave(Widget *origin); | |||||
}; | }; | ||||
struct OutputPort : Port { | struct OutputPort : Port { | ||||
@@ -190,6 +194,8 @@ struct OutputPort : Port { | |||||
void onDragStart(); | void onDragStart(); | ||||
void onDragDrop(Widget *origin); | void onDragDrop(Widget *origin); | ||||
void onDragEnter(Widget *origin); | |||||
void onDragLeave(Widget *origin); | |||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
@@ -104,6 +104,8 @@ struct Widget { | |||||
/** Called when a widget responds to `onMouseMove` and is being dragged */ | /** Called when a widget responds to `onMouseMove` and is being dragged */ | ||||
virtual void onDragMove(Vec mouseRel) {} | virtual void onDragMove(Vec mouseRel) {} | ||||
/** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */ | /** 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 onDragDrop(Widget *origin) {} | ||||
virtual void onAction() {} | virtual void onAction() {} | ||||
@@ -318,6 +320,7 @@ struct Scene : OpaqueWidget { | |||||
extern Vec gMousePos; | extern Vec gMousePos; | ||||
extern Widget *gHoveredWidget; | extern Widget *gHoveredWidget; | ||||
extern Widget *gDraggedWidget; | extern Widget *gDraggedWidget; | ||||
extern Widget *gDragHoveredWidget; | |||||
extern Widget *gSelectedWidget; | extern Widget *gSelectedWidget; | ||||
extern int gGuiFrame; | extern int gGuiFrame; | ||||
@@ -60,6 +60,7 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
gDraggedWidget->onDragEnd(); | gDraggedWidget->onDragEnd(); | ||||
} | } | ||||
gDraggedWidget = NULL; | gDraggedWidget = NULL; | ||||
gDragHoveredWidget = NULL; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -69,27 +70,33 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
Vec mouseRel = mousePos.minus(gMousePos); | Vec mouseRel = mousePos.minus(gMousePos); | ||||
gMousePos = mousePos; | 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) { | if (gDraggedWidget) { | ||||
// onDragMove | // onDragMove | ||||
// Drag slower if Ctrl is held | // 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 { | else { | ||||
// onMouseMove | |||||
Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel); | |||||
if (hovered != gHoveredWidget) { | if (hovered != gHoveredWidget) { | ||||
if (gHoveredWidget) { | if (gHoveredWidget) { | ||||
// onMouseLeave | // onMouseLeave | ||||
@@ -99,8 +106,8 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
// onMouseEnter | // onMouseEnter | ||||
hovered->onMouseEnter(); | hovered->onMouseEnter(); | ||||
} | } | ||||
gHoveredWidget = hovered; | |||||
} | } | ||||
gHoveredWidget = hovered; | |||||
} | } | ||||
} | } | ||||
@@ -5,6 +5,7 @@ namespace rack { | |||||
Vec gMousePos; | Vec gMousePos; | ||||
Widget *gHoveredWidget = NULL; | Widget *gHoveredWidget = NULL; | ||||
Widget *gDraggedWidget = NULL; | Widget *gDraggedWidget = NULL; | ||||
Widget *gDragHoveredWidget = NULL; | |||||
Widget *gSelectedWidget = NULL; | Widget *gSelectedWidget = NULL; | ||||
int gGuiFrame; | int gGuiFrame; | ||||
@@ -22,11 +22,24 @@ void InputPort::onDragStart() { | |||||
void InputPort::onDragDrop(Widget *origin) { | void InputPort::onDragDrop(Widget *origin) { | ||||
if (connectedWire) return; | if (connectedWire) return; | ||||
if (gRackWidget->activeWire) { | if (gRackWidget->activeWire) { | ||||
gRackWidget->activeWire->hoveredInputPort = NULL; | |||||
if (gRackWidget->activeWire->inputPort) return; | if (gRackWidget->activeWire->inputPort) return; | ||||
gRackWidget->activeWire->inputPort = this; | gRackWidget->activeWire->inputPort = this; | ||||
connectedWire = gRackWidget->activeWire; | 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 | } // namespace rack |
@@ -9,16 +9,15 @@ void Light::draw(NVGcontext *vg) { | |||||
Vec c = box.getCenter(); | Vec c = box.getCenter(); | ||||
Vec r = box.size.div(2.0); | 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); | nvgBeginPath(vg); | ||||
nvgEllipse(vg, c.x, c.y, r.x - 1.0, r.y - 1.0); | nvgEllipse(vg, c.x, c.y, r.x - 1.0, r.y - 1.0); | ||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
nvgStrokeWidth(vg, 1.0); | |||||
nvgStrokeColor(vg, colorOutline); | |||||
nvgStroke(vg); | |||||
// float radius = box.size.x / 2.0; | // float radius = box.size.x / 2.0; | ||||
// NVGcolor icol, ocol; | // NVGcolor icol, ocol; | ||||
// NVGpaint paint; | // NVGpaint paint; | ||||
@@ -22,11 +22,24 @@ void OutputPort::onDragStart() { | |||||
void OutputPort::onDragDrop(Widget *origin) { | void OutputPort::onDragDrop(Widget *origin) { | ||||
if (connectedWire) return; | if (connectedWire) return; | ||||
if (gRackWidget->activeWire) { | if (gRackWidget->activeWire) { | ||||
gRackWidget->activeWire->hoveredOutputPort = NULL; | |||||
if (gRackWidget->activeWire->outputPort) return; | if (gRackWidget->activeWire->outputPort) return; | ||||
gRackWidget->activeWire->outputPort = this; | gRackWidget->activeWire->outputPort = this; | ||||
connectedWire = gRackWidget->activeWire; | 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 | } // namespace rack |
@@ -36,5 +36,4 @@ void Port::onDragEnd() { | |||||
gRackWidget->activeWire = NULL; | gRackWidget->activeWire = NULL; | ||||
} | } | ||||
} // namespace rack | } // namespace rack |
@@ -21,6 +21,8 @@ void RadioButton::onDragDrop(Widget *origin) { | |||||
value = 1.0; | value = 1.0; | ||||
else | else | ||||
value = 0.0; | value = 0.0; | ||||
onAction(); | |||||
} | } | ||||
} | } | ||||
@@ -8,12 +8,10 @@ Widget::~Widget() { | |||||
// You should only delete orphaned widgets | // You should only delete orphaned widgets | ||||
assert(!parent); | assert(!parent); | ||||
// Stop dragging and hovering this widget | // 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(); | clearChildren(); | ||||
} | } | ||||
@@ -71,9 +69,9 @@ void Widget::step() { | |||||
} | } | ||||
void Widget::draw(NVGcontext *vg) { | void Widget::draw(NVGcontext *vg) { | ||||
nvgSave(vg); | |||||
nvgTranslate(vg, box.pos.x, box.pos.y); | nvgTranslate(vg, box.pos.x, box.pos.y); | ||||
for (Widget *child : children) { | for (Widget *child : children) { | ||||
nvgSave(vg); | |||||
child->draw(vg); | child->draw(vg); | ||||
} | } | ||||
nvgRestore(vg); | nvgRestore(vg); | ||||
@@ -7,16 +7,18 @@ namespace rack { | |||||
static void drawPlug(NVGcontext *vg, Vec pos, NVGcolor color) { | static void drawPlug(NVGcontext *vg, Vec pos, NVGcolor color) { | ||||
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | 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); | nvgBeginPath(vg); | ||||
nvgCircle(vg, pos.x, pos.y, 9.5); | nvgCircle(vg, pos.x, pos.y, 9.5); | ||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
// Border | |||||
nvgStrokeWidth(vg, 1.0); | |||||
nvgStrokeColor(vg, colorOutline); | |||||
nvgStroke(vg); | |||||
// Hole | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgCircle(vg, pos.x, pos.y, 5.5); | nvgCircle(vg, pos.x, pos.y, 5.5); | ||||
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | ||||
@@ -118,25 +120,35 @@ void WireWidget::updateWire() { | |||||
} | } | ||||
void WireWidget::draw(NVGcontext *vg) { | void WireWidget::draw(NVGcontext *vg) { | ||||
Vec outputPos, inputPos; | |||||
Vec absolutePos = getAbsolutePos(); | Vec absolutePos = getAbsolutePos(); | ||||
float opacity = dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value / 100.0; | float opacity = dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value / 100.0; | ||||
float tension = dynamic_cast<RackScene*>(gScene)->toolbar->wireTensionSlider->value; | float tension = dynamic_cast<RackScene*>(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) { | if (outputPort) { | ||||
outputPos = Rect(outputPort->getAbsolutePos(), outputPort->box.size).getCenter(); | outputPos = Rect(outputPort->getAbsolutePos(), outputPort->box.size).getCenter(); | ||||
} | } | ||||
else if (hoveredOutputPort) { | |||||
outputPos = Rect(hoveredOutputPort->getAbsolutePos(), hoveredOutputPort->box.size).getCenter(); | |||||
} | |||||
else { | else { | ||||
outputPos = gMousePos; | outputPos = gMousePos; | ||||
opacity = 1.0; | |||||
} | } | ||||
Vec inputPos; | |||||
if (inputPort) { | if (inputPort) { | ||||
inputPos = Rect(inputPort->getAbsolutePos(), inputPort->box.size).getCenter(); | inputPos = Rect(inputPort->getAbsolutePos(), inputPort->box.size).getCenter(); | ||||
} | } | ||||
else if (hoveredInputPort) { | |||||
inputPos = Rect(hoveredInputPort->getAbsolutePos(), hoveredInputPort->box.size).getCenter(); | |||||
} | |||||
else { | else { | ||||
inputPos = gMousePos; | inputPos = gMousePos; | ||||
opacity = 1.0; | |||||
} | } | ||||
outputPos = outputPos.minus(absolutePos); | outputPos = outputPos.minus(absolutePos); | ||||