@@ -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 $@ | |||
@@ -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); | |||
}; | |||
//////////////////// | |||
@@ -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; | |||
@@ -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; | |||
} | |||
} | |||
@@ -5,6 +5,7 @@ namespace rack { | |||
Vec gMousePos; | |||
Widget *gHoveredWidget = NULL; | |||
Widget *gDraggedWidget = NULL; | |||
Widget *gDragHoveredWidget = NULL; | |||
Widget *gSelectedWidget = NULL; | |||
int gGuiFrame; | |||
@@ -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 |
@@ -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; | |||
@@ -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 |
@@ -36,5 +36,4 @@ void Port::onDragEnd() { | |||
gRackWidget->activeWire = NULL; | |||
} | |||
} // namespace rack |
@@ -21,6 +21,8 @@ void RadioButton::onDragDrop(Widget *origin) { | |||
value = 1.0; | |||
else | |||
value = 0.0; | |||
onAction(); | |||
} | |||
} | |||
@@ -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); | |||
@@ -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<RackScene*>(gScene)->toolbar->wireOpacitySlider->value / 100.0; | |||
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) { | |||
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); | |||