| @@ -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 | |||||