@@ -17,6 +17,14 @@ struct Module { | |||||
/** For CPU usage */ | /** For CPU usage */ | ||||
float cpuTime = 0.0; | float cpuTime = 0.0; | ||||
/** Deprecated, use constructor below this one */ | |||||
Module() {} | |||||
/** Constructs Module with a fixed number of params, inputs, and outputs */ | |||||
Module(int numParams, int numInputs, int numOutputs) { | |||||
params.resize(numParams); | |||||
inputs.resize(numInputs); | |||||
outputs.resize(numOutputs); | |||||
} | |||||
virtual ~Module() {} | virtual ~Module() {} | ||||
/** Advances the module by 1 audio frame with duration 1.0 / gSampleRate */ | /** Advances the module by 1 audio frame with duration 1.0 / gSampleRate */ | ||||
@@ -369,10 +369,19 @@ struct ScrollWidget : OpaqueWidget { | |||||
ScrollWidget(); | ScrollWidget(); | ||||
void step(); | void step(); | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel); | |||||
bool onScrollOpaque(Vec scrollRel); | bool onScrollOpaque(Vec scrollRel); | ||||
}; | }; | ||||
struct ZoomWidget : Widget { | |||||
float zoom = 1.0; | |||||
void draw(NVGcontext *vg); | |||||
Widget *onMouseDown(Vec pos, int button); | |||||
Widget *onMouseUp(Vec pos, int button); | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel); | |||||
Widget *onHoverKey(Vec pos, int key); | |||||
Widget *onScroll(Vec pos, Vec scrollRel); | |||||
}; | |||||
struct TextField : OpaqueWidget { | struct TextField : OpaqueWidget { | ||||
std::string text; | std::string text; | ||||
std::string placeholder; | std::string placeholder; | ||||
@@ -29,9 +29,14 @@ static void checkVersion() { | |||||
RackScene::RackScene() { | RackScene::RackScene() { | ||||
scrollWidget = new ScrollWidget(); | scrollWidget = new ScrollWidget(); | ||||
{ | { | ||||
// ZoomWidget *zoomWidget = new ZoomWidget(); | |||||
// zoomWidget->zoom = 0.8; | |||||
// scrollWidget->container->addChild(zoomWidget); | |||||
assert(!gRackWidget); | assert(!gRackWidget); | ||||
gRackWidget = new RackWidget(); | gRackWidget = new RackWidget(); | ||||
scrollWidget->container->addChild(gRackWidget); | scrollWidget->container->addChild(gRackWidget); | ||||
// zoomWidget->addChild(gRackWidget); | |||||
} | } | ||||
addChild(scrollWidget); | addChild(scrollWidget); | ||||
@@ -1,5 +1,6 @@ | |||||
#include <map> | #include <map> | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <thread> | |||||
#include "app.hpp" | #include "app.hpp" | ||||
#include "engine.hpp" | #include "engine.hpp" | ||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
@@ -369,7 +370,8 @@ struct AddModuleMenuItem : MenuItem { | |||||
struct UrlItem : MenuItem { | struct UrlItem : MenuItem { | ||||
std::string url; | std::string url; | ||||
void onAction() { | void onAction() { | ||||
openBrowser(url); | |||||
std::thread t(openBrowser, url); | |||||
t.detach(); | |||||
} | } | ||||
}; | }; | ||||
@@ -56,8 +56,13 @@ struct AudioInterface : Module { | |||||
// in device's sample rate | // in device's sample rate | ||||
DoubleRingBuffer<Frame<8>, (1<<15)> inputSrcBuffer; | DoubleRingBuffer<Frame<8>, (1<<15)> inputSrcBuffer; | ||||
AudioInterface(); | |||||
~AudioInterface(); | |||||
AudioInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
audioInit(); | |||||
} | |||||
~AudioInterface() { | |||||
closeDevice(); | |||||
} | |||||
void step(); | void step(); | ||||
void stepStream(const float *input, float *output, int numFrames); | void stepStream(const float *input, float *output, int numFrames); | ||||
@@ -117,17 +122,6 @@ struct AudioInterface : Module { | |||||
}; | }; | ||||
AudioInterface::AudioInterface() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
audioInit(); | |||||
} | |||||
AudioInterface::~AudioInterface() { | |||||
closeDevice(); | |||||
} | |||||
void AudioInterface::step() { | void AudioInterface::step() { | ||||
if (!stream) | if (!stream) | ||||
return; | return; | ||||
@@ -52,8 +52,13 @@ struct MidiInterface : Module { | |||||
bool retrigger = false; | bool retrigger = false; | ||||
bool retriggered = false; | bool retriggered = false; | ||||
MidiInterface(); | |||||
~MidiInterface(); | |||||
MidiInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
midiInit(); | |||||
} | |||||
~MidiInterface() { | |||||
setPortId(-1); | |||||
} | |||||
void step(); | void step(); | ||||
int getPortCount(); | int getPortCount(); | ||||
@@ -101,17 +106,6 @@ struct MidiInterface : Module { | |||||
}; | }; | ||||
MidiInterface::MidiInterface() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
midiInit(); | |||||
} | |||||
MidiInterface::~MidiInterface() { | |||||
setPortId(-1); | |||||
} | |||||
void MidiInterface::step() { | void MidiInterface::step() { | ||||
if (stream) { | if (stream) { | ||||
// Read MIDI events | // Read MIDI events | ||||
@@ -25,7 +25,6 @@ static std::thread thread; | |||||
static VIPMutex vipMutex; | static VIPMutex vipMutex; | ||||
static std::vector<Module*> modules; | static std::vector<Module*> modules; | ||||
// Merely used for keeping track of which module inputs point to which module outputs, to prevent pointer mistakes and make the rack API more rigorous | |||||
static std::vector<Wire*> wires; | static std::vector<Wire*> wires; | ||||
// Parameter interpolation | // Parameter interpolation | ||||
@@ -137,6 +137,11 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
gHoveredWidget = hovered; | gHoveredWidget = hovered; | ||||
} | } | ||||
} | } | ||||
if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) { | |||||
// TODO | |||||
// Define a new global called gScrollWidget, which remembers the widget where middle-click was first pressed | |||||
gScene->onScroll(mousePos, mouseRel); | |||||
} | |||||
} | } | ||||
void cursorEnterCallback(GLFWwindow* window, int entered) { | void cursorEnterCallback(GLFWwindow* window, int entered) { | ||||
@@ -71,8 +71,11 @@ void FramebufferWidget::step() { | |||||
} | } | ||||
void FramebufferWidget::draw(NVGcontext *vg) { | void FramebufferWidget::draw(NVGcontext *vg) { | ||||
if (!internal->fb) | |||||
if (!internal->fb) { | |||||
// Bypass framebuffer cache entirely | |||||
// Widget::draw(vg); | |||||
return; | return; | ||||
} | |||||
// Draw framebuffer image | // Draw framebuffer image | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
@@ -35,17 +35,6 @@ void ScrollWidget::step() { | |||||
Widget::step(); | Widget::step(); | ||||
} | } | ||||
Widget *ScrollWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) { | |||||
offset = offset.minus(mouseRel); | |||||
return this; | |||||
} | |||||
Widget *w = Widget::onMouseMove(pos, mouseRel); | |||||
if (w) return w; | |||||
return NULL; | |||||
} | |||||
bool ScrollWidget::onScrollOpaque(Vec scrollRel) { | bool ScrollWidget::onScrollOpaque(Vec scrollRel) { | ||||
offset = offset.minus(scrollRel); | offset = offset.minus(scrollRel); | ||||
return true; | return true; | ||||
@@ -0,0 +1,33 @@ | |||||
#include "widgets.hpp" | |||||
namespace rack { | |||||
void ZoomWidget::draw(NVGcontext *vg) { | |||||
nvgScale(vg, zoom, zoom); | |||||
Widget::draw(vg); | |||||
} | |||||
Widget *ZoomWidget::onMouseDown(Vec pos, int button) { | |||||
return Widget::onMouseDown(pos.div(zoom), button); | |||||
} | |||||
Widget *ZoomWidget::onMouseUp(Vec pos, int button) { | |||||
return Widget::onMouseUp(pos.div(zoom), button); | |||||
} | |||||
Widget *ZoomWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
return Widget::onMouseMove(pos.div(zoom), mouseRel); | |||||
} | |||||
Widget *ZoomWidget::onHoverKey(Vec pos, int key) { | |||||
return Widget::onHoverKey(pos.div(zoom), key); | |||||
} | |||||
Widget *ZoomWidget::onScroll(Vec pos, Vec scrollRel) { | |||||
return Widget::onScroll(pos.div(zoom), scrollRel); | |||||
} | |||||
} // namespace rack |