@@ -74,6 +74,9 @@ include compile.mk | |||||
dist: all | dist: all | ||||
ifndef VERSION | |||||
$(error VERSION must be defined when calling make) | |||||
endif | |||||
rm -rf dist | rm -rf dist | ||||
$(MAKE) -C plugins/Fundamental dist | $(MAKE) -C plugins/Fundamental dist | ||||
@@ -144,7 +147,7 @@ ifeq ($(ARCH), lin) | |||||
cp dep/lib/libcurl.so.4 dist/Rack/ | cp dep/lib/libcurl.so.4 dist/Rack/ | ||||
cp dep/lib/libzip.so.5 dist/Rack/ | cp dep/lib/libzip.so.5 dist/Rack/ | ||||
cp dep/lib/libportaudio.so.2 dist/Rack/ | cp dep/lib/libportaudio.so.2 dist/Rack/ | ||||
cp dep/lib/librtmidi.so dist/Rack/ | |||||
cp dep/lib/librtmidi.so.4 dist/Rack/ | |||||
mkdir -p dist/Rack/plugins | mkdir -p dist/Rack/plugins | ||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | ||||
endif | endif | ||||
@@ -20,7 +20,7 @@ Rack's dependencies (GLEW, glfw, etc) do not need to be installed on your system | |||||
### Mac | ### Mac | ||||
Install [Xcode](https://developer.apple.com/xcode/). | Install [Xcode](https://developer.apple.com/xcode/). | ||||
Install [CMake](https://cmake.org/) and wget, preferably from [Homebrew](https://brew.sh/). | |||||
Install [CMake](https://cmake.org/) (for some of Rack's dependencies) and wget, preferably from [Homebrew](https://brew.sh/). | |||||
### Windows | ### Windows | ||||
@@ -38,7 +38,7 @@ With your distro's package manager, make sure you have installed `gcc`, `make`, | |||||
*If the build fails for you, please report the issue with a detailed error message to help the portability of Rack.* | *If the build fails for you, please report the issue with a detailed error message to help the portability of Rack.* | ||||
Clone this repository and `cd` into it. | Clone this repository and `cd` into it. | ||||
If you would like to build a previous version instead of the master branch, run `git checkout v0.3.2` for example. | |||||
If you would like to build a previous version of Rack instead of the master branch, check out the desired tag with `git checkout v0.4.0` for example. | |||||
Clone submodules. | Clone submodules. | ||||
@@ -61,6 +61,8 @@ Run Rack. | |||||
## Building plugins | ## Building plugins | ||||
Be sure to check out and build the version of Rack you wish to build your plugins against. | |||||
Clone your favorite plugin in the `plugins/` directory. e.g.: | Clone your favorite plugin in the `plugins/` directory. e.g.: | ||||
cd plugins | cd plugins | ||||
@@ -1,12 +1,14 @@ | |||||
VERSION ?= dev | |||||
FLAGS += -DVERSION=$(VERSION) -DVERSION_$(subst .,_,$(VERSION)) | |||||
ifdef VERSION | |||||
FLAGS += -DVERSION=$(VERSION) | |||||
endif | |||||
# Generate dependency files alongside the object files | # Generate dependency files alongside the object files | ||||
FLAGS += -MMD | FLAGS += -MMD | ||||
FLAGS += -g | |||||
# Optimization | # Optimization | ||||
FLAGS += -O3 -march=nocona -ffast-math | FLAGS += -O3 -march=nocona -ffast-math | ||||
FLAGS += -Wall | |||||
FLAGS += -g | |||||
FLAGS += -Wall -Wextra -Wno-unused-parameter | |||||
CXXFLAGS += -Wsuggest-override | |||||
CXXFLAGS += -std=c++11 | CXXFLAGS += -std=c++11 | ||||
@@ -50,22 +50,24 @@ struct ModuleWidget : OpaqueWidget { | |||||
/** Resets the parameters of the module and calls the Module's randomize(). | /** Resets the parameters of the module and calls the Module's randomize(). | ||||
Called when the user clicks Initialize in the context menu. | Called when the user clicks Initialize in the context menu. | ||||
*/ | */ | ||||
virtual void initialize(); | |||||
virtual void reset(); | |||||
/** Deprecated */ | |||||
virtual void initialize() final {} | |||||
/** Randomizes the parameters of the module and calls the Module's randomize(). | /** Randomizes the parameters of the module and calls the Module's randomize(). | ||||
Called when the user clicks Randomize in the context menu. | Called when the user clicks Randomize in the context menu. | ||||
*/ | */ | ||||
virtual void randomize(); | virtual void randomize(); | ||||
virtual Menu *createContextMenu(); | virtual Menu *createContextMenu(); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
Vec dragPos; | Vec dragPos; | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel); | |||||
Widget *onHoverKey(Vec pos, int key); | |||||
void onDragStart(); | |||||
void onDragMove(Vec mouseRel); | |||||
void onDragEnd(); | |||||
void onMouseDownOpaque(int button); | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
void onMouseDownOpaque(int button) override; | |||||
}; | }; | ||||
struct ValueLight; | struct ValueLight; | ||||
@@ -85,7 +87,7 @@ struct WireWidget : OpaqueWidget { | |||||
void updateWire(); | void updateWire(); | ||||
Vec getOutputPos(); | Vec getOutputPos(); | ||||
Vec getInputPos(); | Vec getInputPos(); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
void drawPlugs(NVGcontext *vg); | void drawPlugs(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -99,7 +101,7 @@ struct WireContainer : TransparentWidget { | |||||
void removeAllWires(Port *port); | void removeAllWires(Port *port); | ||||
/** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */ | /** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */ | ||||
WireWidget *getTopWire(Port *port); | WireWidget *getTopWire(Port *port); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct RackWidget : OpaqueWidget { | struct RackWidget : OpaqueWidget { | ||||
@@ -113,7 +115,10 @@ struct RackWidget : OpaqueWidget { | |||||
RackWidget(); | RackWidget(); | ||||
~RackWidget(); | ~RackWidget(); | ||||
/** Completely clear the rack's modules and wires */ | |||||
void clear(); | void clear(); | ||||
/** Clears the rack and loads the template patch */ | |||||
void reset(); | |||||
void openDialog(); | void openDialog(); | ||||
void saveDialog(); | void saveDialog(); | ||||
void saveAsDialog(); | void saveAsDialog(); | ||||
@@ -130,20 +135,20 @@ struct RackWidget : OpaqueWidget { | |||||
bool requestModuleBox(ModuleWidget *m, Rect box); | bool requestModuleBox(ModuleWidget *m, Rect box); | ||||
/** Moves a module to the closest non-colliding position */ | /** Moves a module to the closest non-colliding position */ | ||||
bool requestModuleBoxNearest(ModuleWidget *m, Rect box); | bool requestModuleBoxNearest(ModuleWidget *m, Rect box); | ||||
void step(); | |||||
void draw(NVGcontext *vg); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
void onMouseDownOpaque(int button); | |||||
void onMouseDownOpaque(int button) override; | |||||
}; | }; | ||||
struct RackRail : TransparentWidget { | struct RackRail : TransparentWidget { | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct Panel : TransparentWidget { | struct Panel : TransparentWidget { | ||||
NVGcolor backgroundColor; | NVGcolor backgroundColor; | ||||
std::shared_ptr<Image> backgroundImage; | std::shared_ptr<Image> backgroundImage; | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct SVGPanel : FramebufferWidget { | struct SVGPanel : FramebufferWidget { | ||||
@@ -156,13 +161,13 @@ struct SVGPanel : FramebufferWidget { | |||||
struct CircularShadow : TransparentWidget { | struct CircularShadow : TransparentWidget { | ||||
float blur = 0.0; | float blur = 0.0; | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct Light : TransparentWidget { | struct Light : TransparentWidget { | ||||
NVGcolor bgColor = nvgRGBf(0, 0, 0); | NVGcolor bgColor = nvgRGBf(0, 0, 0); | ||||
NVGcolor color = nvgRGBf(1, 1, 1); | NVGcolor color = nvgRGBf(1, 1, 1); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct ParamWidget : OpaqueWidget, QuantityWidget { | struct ParamWidget : OpaqueWidget, QuantityWidget { | ||||
@@ -176,22 +181,25 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *rootJ); | void fromJson(json_t *rootJ); | ||||
virtual void randomize(); | virtual void randomize(); | ||||
void onMouseDownOpaque(int button); | |||||
void onChange(); | |||||
void onMouseDownOpaque(int button) override; | |||||
void onChange() override; | |||||
}; | }; | ||||
/** Implements vertical dragging behavior for ParamWidgets */ | /** Implements vertical dragging behavior for ParamWidgets */ | ||||
struct Knob : ParamWidget { | struct Knob : ParamWidget { | ||||
void onDragStart(); | |||||
void onDragMove(Vec mouseRel); | |||||
void onDragEnd(); | |||||
/** Snap to nearest integer while dragging */ | |||||
bool snap = false; | |||||
float dragValue; | |||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
/** Tell engine to smoothly vary this parameter */ | /** Tell engine to smoothly vary this parameter */ | ||||
void onChange(); | |||||
void onChange() override; | |||||
}; | }; | ||||
struct SpriteKnob : virtual Knob, SpriteWidget { | struct SpriteKnob : virtual Knob, SpriteWidget { | ||||
int minIndex, maxIndex, spriteCount; | int minIndex, maxIndex, spriteCount; | ||||
void step(); | |||||
void step() override; | |||||
}; | }; | ||||
/** A knob which rotates an SVG and caches it in a framebuffer */ | /** A knob which rotates an SVG and caches it in a framebuffer */ | ||||
@@ -204,16 +212,8 @@ struct SVGKnob : virtual Knob, FramebufferWidget { | |||||
SVGKnob(); | SVGKnob(); | ||||
void setSVG(std::shared_ptr<SVG> svg); | void setSVG(std::shared_ptr<SVG> svg); | ||||
void step(); | |||||
void onChange(); | |||||
}; | |||||
/** Snaps to the nearest integer value on mouse release */ | |||||
struct SnapKnob : virtual Knob { | |||||
void onDragEnd() { | |||||
setValue(roundf(value)); | |||||
Knob::onDragEnd(); | |||||
} | |||||
void step() override; | |||||
void onChange() override; | |||||
}; | }; | ||||
struct SVGSlider : Knob, FramebufferWidget { | struct SVGSlider : Knob, FramebufferWidget { | ||||
@@ -224,8 +224,8 @@ struct SVGSlider : Knob, FramebufferWidget { | |||||
SVGWidget *handle; | SVGWidget *handle; | ||||
SVGSlider(); | SVGSlider(); | ||||
void step(); | |||||
void onChange(); | |||||
void step() override; | |||||
void onChange() override; | |||||
}; | }; | ||||
struct Switch : ParamWidget { | struct Switch : ParamWidget { | ||||
@@ -239,13 +239,13 @@ struct SVGSwitch : virtual Switch, FramebufferWidget { | |||||
SVGSwitch(); | SVGSwitch(); | ||||
/** Adds an SVG file to represent the next switch position */ | /** Adds an SVG file to represent the next switch position */ | ||||
void addFrame(std::shared_ptr<SVG> svg); | void addFrame(std::shared_ptr<SVG> svg); | ||||
void step(); | |||||
void onChange(); | |||||
void step() override; | |||||
void onChange() override; | |||||
}; | }; | ||||
/** A switch that cycles through each mechanical position */ | /** A switch that cycles through each mechanical position */ | ||||
struct ToggleSwitch : virtual Switch { | struct ToggleSwitch : virtual Switch { | ||||
void onDragStart() { | |||||
void onDragStart() override { | |||||
// Cycle through values | // Cycle through values | ||||
// e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | // e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | ||||
if (value >= maxValue) | if (value >= maxValue) | ||||
@@ -258,11 +258,11 @@ struct ToggleSwitch : virtual Switch { | |||||
/** A switch that is turned on when held */ | /** A switch that is turned on when held */ | ||||
struct MomentarySwitch : virtual Switch { | struct MomentarySwitch : virtual Switch { | ||||
/** Don't randomize state */ | /** Don't randomize state */ | ||||
void randomize() {} | |||||
void onDragStart() { | |||||
void randomize() override {} | |||||
void onDragStart() override { | |||||
setValue(maxValue); | setValue(maxValue); | ||||
} | } | ||||
void onDragEnd() { | |||||
void onDragEnd() override { | |||||
setValue(minValue); | setValue(minValue); | ||||
} | } | ||||
}; | }; | ||||
@@ -282,20 +282,20 @@ struct Port : OpaqueWidget { | |||||
int portId; | int portId; | ||||
~Port(); | ~Port(); | ||||
void draw(NVGcontext *vg); | |||||
void onMouseDownOpaque(int button); | |||||
void onDragEnd(); | |||||
void onDragStart(); | |||||
void onDragDrop(Widget *origin); | |||||
void onDragEnter(Widget *origin); | |||||
void onDragLeave(Widget *origin); | |||||
void draw(NVGcontext *vg) override; | |||||
void onMouseDownOpaque(int button) override; | |||||
void onDragEnd() override; | |||||
void onDragStart() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
void onDragEnter(Widget *origin) override; | |||||
void onDragLeave(Widget *origin) override; | |||||
}; | }; | ||||
struct SVGPort : Port, FramebufferWidget { | struct SVGPort : Port, FramebufferWidget { | ||||
SVGWidget *background; | SVGWidget *background; | ||||
SVGPort(); | SVGPort(); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
/** If you don't add these to your ModuleWidget, they will fall out of the rack... */ | /** If you don't add these to your ModuleWidget, they will fall out of the rack... */ | ||||
@@ -316,7 +316,7 @@ struct Toolbar : OpaqueWidget { | |||||
RadioButton *plugLightButton; | RadioButton *plugLightButton; | ||||
Toolbar(); | Toolbar(); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct PluginManagerWidget : Widget { | struct PluginManagerWidget : Widget { | ||||
@@ -324,7 +324,7 @@ struct PluginManagerWidget : Widget { | |||||
Widget *manageWidget; | Widget *manageWidget; | ||||
Widget *downloadWidget; | Widget *downloadWidget; | ||||
PluginManagerWidget(); | PluginManagerWidget(); | ||||
void step(); | |||||
void step() override; | |||||
}; | }; | ||||
struct RackScene : Scene { | struct RackScene : Scene { | ||||
@@ -332,9 +332,9 @@ struct RackScene : Scene { | |||||
ZoomWidget *zoomWidget; | ZoomWidget *zoomWidget; | ||||
RackScene(); | RackScene(); | ||||
void step(); | |||||
void draw(NVGcontext *vg); | |||||
Widget *onHoverKey(Vec pos, int key); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
@@ -57,7 +57,11 @@ struct RoundHugeBlackKnob : RoundBlackKnob { | |||||
} | } | ||||
}; | }; | ||||
struct RoundSmallBlackSnapKnob : RoundSmallBlackKnob, SnapKnob {}; | |||||
struct RoundSmallBlackSnapKnob : RoundSmallBlackKnob { | |||||
RoundSmallBlackSnapKnob() { | |||||
snap = true; | |||||
} | |||||
}; | |||||
struct Davies1900hKnob : SVGKnob { | struct Davies1900hKnob : SVGKnob { | ||||
@@ -109,7 +113,11 @@ struct Davies1900hSmallBlackKnob : Davies1900hKnob { | |||||
} | } | ||||
}; | }; | ||||
struct Davies1900hSmallBlackSnapKnob : Davies1900hSmallBlackKnob, SnapKnob {}; | |||||
struct Davies1900hSmallBlackSnapKnob : Davies1900hSmallBlackKnob { | |||||
Davies1900hSmallBlackSnapKnob() { | |||||
snap = true; | |||||
} | |||||
}; | |||||
struct Rogan : SVGKnob { | struct Rogan : SVGKnob { | ||||
@@ -366,7 +374,11 @@ struct BefacoBigKnob : SVGKnob { | |||||
} | } | ||||
}; | }; | ||||
struct BefacoBigSnapKnob : BefacoBigKnob, SnapKnob {}; | |||||
struct BefacoBigSnapKnob : BefacoBigKnob { | |||||
BefacoBigSnapKnob() { | |||||
snap = true; | |||||
} | |||||
}; | |||||
struct BefacoTinyKnob : SVGKnob { | struct BefacoTinyKnob : SVGKnob { | ||||
BefacoTinyKnob() { | BefacoTinyKnob() { | ||||
@@ -426,7 +438,7 @@ struct CL1362Port : SVGPort { | |||||
struct ValueLight : Light { | struct ValueLight : Light { | ||||
float *value = NULL; | float *value = NULL; | ||||
virtual void setValue(float v) {} | virtual void setValue(float v) {} | ||||
void step() { | |||||
void step() override { | |||||
if (value) | if (value) | ||||
setValue(*value); | setValue(*value); | ||||
} | } | ||||
@@ -434,7 +446,7 @@ struct ValueLight : Light { | |||||
struct ColorValueLight : ValueLight { | struct ColorValueLight : ValueLight { | ||||
NVGcolor baseColor; | NVGcolor baseColor; | ||||
void setValue(float v) { | |||||
void setValue(float v) override { | |||||
v = sqrtBipolar(v); | v = sqrtBipolar(v); | ||||
color = baseColor; | color = baseColor; | ||||
color.a *= clampf(v, 0.0, 1.0); | color.a *= clampf(v, 0.0, 1.0); | ||||
@@ -462,7 +474,7 @@ struct GreenValueLight : ColorValueLight { | |||||
struct PolarityLight : ValueLight { | struct PolarityLight : ValueLight { | ||||
NVGcolor posColor; | NVGcolor posColor; | ||||
NVGcolor negColor; | NVGcolor negColor; | ||||
void setValue(float v) { | |||||
void setValue(float v) override { | |||||
v = sqrtBipolar(v); | v = sqrtBipolar(v); | ||||
color = (v >= 0.0) ? posColor : negColor; | color = (v >= 0.0) ? posColor : negColor; | ||||
color.a *= clampf(fabsf(v), 0.0, 1.0); | color.a *= clampf(fabsf(v), 0.0, 1.0); | ||||
@@ -478,7 +490,7 @@ struct GreenRedPolarityLight : PolarityLight { | |||||
struct ModeValueLight : ValueLight { | struct ModeValueLight : ValueLight { | ||||
std::vector<NVGcolor> colors; | std::vector<NVGcolor> colors; | ||||
void setValue(float v) { | |||||
void setValue(float v) override { | |||||
int mode = clampi((int)roundf(v), 0, colors.size()); | int mode = clampi((int)roundf(v), 0, colors.size()); | ||||
color = colors[mode]; | color = colors[mode]; | ||||
} | } | ||||
@@ -615,8 +627,7 @@ struct ScrewBlack : SVGScrew { | |||||
struct LightPanel : Panel { | struct LightPanel : Panel { | ||||
LightPanel() { | LightPanel() { | ||||
// backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); | |||||
backgroundColor = nvgRGB(0xf0, 0xf0, 0xf0); | |||||
backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); | |||||
} | } | ||||
}; | }; | ||||
@@ -56,8 +56,10 @@ struct Module { | |||||
virtual void fromJson(json_t *root) {} | virtual void fromJson(json_t *root) {} | ||||
/** Override these to implement spacial behavior when user clicks Initialize and Randomize */ | /** Override these to implement spacial behavior when user clicks Initialize and Randomize */ | ||||
virtual void initialize() {} | |||||
virtual void reset() {} | |||||
virtual void randomize() {} | virtual void randomize() {} | ||||
/** Deprecated */ | |||||
virtual void initialize() final {} | |||||
}; | }; | ||||
struct Wire { | struct Wire { | ||||
@@ -82,8 +84,8 @@ void engineRemoveWire(Wire *wire); | |||||
void engineSetParam(Module *module, int paramId, float value); | void engineSetParam(Module *module, int paramId, float value); | ||||
void engineSetParamSmooth(Module *module, int paramId, float value); | void engineSetParamSmooth(Module *module, int paramId, float value); | ||||
void engineSetSampleRate(float sampleRate); | void engineSetSampleRate(float sampleRate); | ||||
float engineGetSampleRate(); | |||||
extern float gSampleRate; | |||||
extern bool gPaused; | extern bool gPaused; | ||||
@@ -20,7 +20,7 @@ namespace rack { | |||||
template <class TModuleWidget> | template <class TModuleWidget> | ||||
Model *createModel(Plugin *plugin, std::string slug, std::string name) { | Model *createModel(Plugin *plugin, std::string slug, std::string name) { | ||||
struct TModel : Model { | struct TModel : Model { | ||||
ModuleWidget *createModuleWidget() { | |||||
ModuleWidget *createModuleWidget() override { | |||||
ModuleWidget *moduleWidget = new TModuleWidget(); | ModuleWidget *moduleWidget = new TModuleWidget(); | ||||
moduleWidget->model = this; | moduleWidget->model = this; | ||||
return moduleWidget; | return moduleWidget; | ||||
@@ -141,7 +141,7 @@ struct TransformWidget : Widget { | |||||
void translate(Vec delta); | void translate(Vec delta); | ||||
void rotate(float angle); | void rotate(float angle); | ||||
void scale(Vec s); | void scale(Vec s); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
@@ -151,33 +151,33 @@ struct TransformWidget : Widget { | |||||
/** Widget that does not respond to events */ | /** Widget that does not respond to events */ | ||||
struct TransparentWidget : virtual Widget { | struct TransparentWidget : virtual Widget { | ||||
Widget *onMouseDown(Vec pos, int button) {return NULL;} | |||||
Widget *onMouseUp(Vec pos, int button) {return NULL;} | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) {return NULL;} | |||||
Widget *onScroll(Vec pos, Vec scrollRel) {return NULL;} | |||||
Widget *onMouseDown(Vec pos, int button) override {return NULL;} | |||||
Widget *onMouseUp(Vec pos, int button) override {return NULL;} | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override {return NULL;} | |||||
Widget *onScroll(Vec pos, Vec scrollRel) override {return NULL;} | |||||
}; | }; | ||||
/** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */ | /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */ | ||||
struct OpaqueWidget : virtual Widget { | struct OpaqueWidget : virtual Widget { | ||||
Widget *onMouseDown(Vec pos, int button) { | |||||
Widget *onMouseDown(Vec pos, int button) override { | |||||
Widget *w = Widget::onMouseDown(pos, button); | Widget *w = Widget::onMouseDown(pos, button); | ||||
if (w) return w; | if (w) return w; | ||||
onMouseDownOpaque(button); | onMouseDownOpaque(button); | ||||
return this; | return this; | ||||
} | } | ||||
Widget *onMouseUp(Vec pos, int button) { | |||||
Widget *onMouseUp(Vec pos, int button) override { | |||||
Widget *w = Widget::onMouseUp(pos, button); | Widget *w = Widget::onMouseUp(pos, button); | ||||
if (w) return w; | if (w) return w; | ||||
onMouseUpOpaque(button); | onMouseUpOpaque(button); | ||||
return this; | return this; | ||||
} | } | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel) { | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override { | |||||
Widget *w = Widget::onMouseMove(pos, mouseRel); | Widget *w = Widget::onMouseMove(pos, mouseRel); | ||||
if (w) return w; | if (w) return w; | ||||
onMouseMoveOpaque(mouseRel); | onMouseMoveOpaque(mouseRel); | ||||
return this; | return this; | ||||
} | } | ||||
Widget *onScroll(Vec pos, Vec scrollRel) { | |||||
Widget *onScroll(Vec pos, Vec scrollRel) override { | |||||
Widget *w = Widget::onScroll(pos, scrollRel); | Widget *w = Widget::onScroll(pos, scrollRel); | ||||
if (w) return w; | if (w) return w; | ||||
if (onScrollOpaque(scrollRel)) | if (onScrollOpaque(scrollRel)) | ||||
@@ -199,22 +199,22 @@ struct SpriteWidget : virtual Widget { | |||||
Vec spriteSize; | Vec spriteSize; | ||||
std::shared_ptr<Image> spriteImage; | std::shared_ptr<Image> spriteImage; | ||||
int index = 0; | int index = 0; | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct SVGWidget : virtual Widget { | struct SVGWidget : virtual Widget { | ||||
std::shared_ptr<SVG> svg; | std::shared_ptr<SVG> svg; | ||||
/** Sets the box size to the svg image size */ | /** Sets the box size to the svg image size */ | ||||
void wrap(); | void wrap(); | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
/** Caches a widget's draw() result to a framebuffer so it is called less frequently | /** Caches a widget's draw() result to a framebuffer so it is called less frequently | ||||
When `dirty` is true, its children will be re-rendered on the next call to step(). | |||||
When `dirty` is true, its children will be re-rendered on the next call to step() override. | |||||
Events are not passed to the underlying scene. | Events are not passed to the underlying scene. | ||||
*/ | */ | ||||
struct FramebufferWidget : virtual Widget { | struct FramebufferWidget : virtual Widget { | ||||
/** Set this to true to re-render the children to the framebuffer in the next step() */ | |||||
/** Set this to true to re-render the children to the framebuffer in the next step() override */ | |||||
bool dirty = true; | bool dirty = true; | ||||
/** A margin in pixels around the children in the framebuffer | /** A margin in pixels around the children in the framebuffer | ||||
This prevents cutting the rendered SVG off on the box edges. | This prevents cutting the rendered SVG off on the box edges. | ||||
@@ -228,8 +228,8 @@ struct FramebufferWidget : virtual Widget { | |||||
FramebufferWidget(); | FramebufferWidget(); | ||||
~FramebufferWidget(); | ~FramebufferWidget(); | ||||
void step(); | |||||
void draw(NVGcontext *vg); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
int getImageHandle(); | int getImageHandle(); | ||||
}; | }; | ||||
@@ -263,14 +263,14 @@ struct Label : Widget { | |||||
Label() { | Label() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
// Deletes itself from parent when clicked | // Deletes itself from parent when clicked | ||||
struct MenuOverlay : OpaqueWidget { | struct MenuOverlay : OpaqueWidget { | ||||
void onDragDrop(Widget *origin); | |||||
bool onScrollOpaque(Vec scrollRel) {return true;} | |||||
Widget *onHoverKey(Vec pos, int key); | |||||
void onDragDrop(Widget *origin) override; | |||||
bool onScrollOpaque(Vec scrollRel) override {return true;} | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
}; | }; | ||||
struct MenuEntry; | struct MenuEntry; | ||||
@@ -289,9 +289,9 @@ struct Menu : OpaqueWidget { | |||||
void pushChild(Widget *child); | void pushChild(Widget *child); | ||||
void setChildMenu(Menu *menu); | void setChildMenu(Menu *menu); | ||||
void fit(); | void fit(); | ||||
void step(); | |||||
void draw(NVGcontext *vg); | |||||
bool onScrollOpaque(Vec scrollRel); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
bool onScrollOpaque(Vec scrollRel) override; | |||||
}; | }; | ||||
struct MenuEntry : OpaqueWidget { | struct MenuEntry : OpaqueWidget { | ||||
@@ -304,16 +304,16 @@ struct MenuEntry : OpaqueWidget { | |||||
}; | }; | ||||
struct MenuLabel : MenuEntry { | struct MenuLabel : MenuEntry { | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct MenuItem : MenuEntry { | struct MenuItem : MenuEntry { | ||||
float computeMinWidth(NVGcontext *vg); | |||||
void draw(NVGcontext *vg); | |||||
float computeMinWidth(NVGcontext *vg) override; | |||||
void draw(NVGcontext *vg) override; | |||||
virtual Menu *createChildMenu() {return NULL;} | virtual Menu *createChildMenu() {return NULL;} | ||||
void onMouseEnter(); | |||||
void onDragDrop(Widget *origin); | |||||
void onMouseEnter() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
}; | }; | ||||
struct Button : OpaqueWidget { | struct Button : OpaqueWidget { | ||||
@@ -323,16 +323,16 @@ struct Button : OpaqueWidget { | |||||
Button() { | Button() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void onMouseEnter(); | |||||
void onMouseLeave(); | |||||
void onDragStart(); | |||||
void onDragEnd(); | |||||
void onDragDrop(Widget *origin); | |||||
void draw(NVGcontext *vg) override; | |||||
void onMouseEnter() override; | |||||
void onMouseLeave() override; | |||||
void onDragStart() override; | |||||
void onDragEnd() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
}; | }; | ||||
struct ChoiceButton : Button { | struct ChoiceButton : Button { | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct RadioButton : OpaqueWidget, QuantityWidget { | struct RadioButton : OpaqueWidget, QuantityWidget { | ||||
@@ -341,10 +341,10 @@ struct RadioButton : OpaqueWidget, QuantityWidget { | |||||
RadioButton() { | RadioButton() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void onMouseEnter(); | |||||
void onMouseLeave(); | |||||
void onDragDrop(Widget *origin); | |||||
void draw(NVGcontext *vg) override; | |||||
void onMouseEnter() override; | |||||
void onMouseLeave() override; | |||||
void onDragDrop(Widget *origin) override; | |||||
}; | }; | ||||
struct Slider : OpaqueWidget, QuantityWidget { | struct Slider : OpaqueWidget, QuantityWidget { | ||||
@@ -353,10 +353,10 @@ struct Slider : OpaqueWidget, QuantityWidget { | |||||
Slider() { | Slider() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void onDragStart(); | |||||
void onDragMove(Vec mouseRel); | |||||
void onDragEnd(); | |||||
void draw(NVGcontext *vg) override; | |||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
}; | }; | ||||
/** Parent must be a ScrollWidget */ | /** Parent must be a ScrollWidget */ | ||||
@@ -367,10 +367,10 @@ struct ScrollBar : OpaqueWidget { | |||||
ScrollBar() { | ScrollBar() { | ||||
box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void onDragStart(); | |||||
void onDragMove(Vec mouseRel); | |||||
void onDragEnd(); | |||||
void draw(NVGcontext *vg) override; | |||||
void onDragStart() override; | |||||
void onDragMove(Vec mouseRel) override; | |||||
void onDragEnd() override; | |||||
}; | }; | ||||
/** Handles a container with ScrollBar */ | /** Handles a container with ScrollBar */ | ||||
@@ -381,19 +381,19 @@ struct ScrollWidget : OpaqueWidget { | |||||
Vec offset; | Vec offset; | ||||
ScrollWidget(); | ScrollWidget(); | ||||
void step(); | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel); | |||||
bool onScrollOpaque(Vec scrollRel); | |||||
void step() override; | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
bool onScrollOpaque(Vec scrollRel) override; | |||||
}; | }; | ||||
struct ZoomWidget : Widget { | struct ZoomWidget : Widget { | ||||
float zoom = 1.0; | 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); | |||||
void draw(NVGcontext *vg) override; | |||||
Widget *onMouseDown(Vec pos, int button) override; | |||||
Widget *onMouseUp(Vec pos, int button) override; | |||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
Widget *onHoverKey(Vec pos, int key) override; | |||||
Widget *onScroll(Vec pos, Vec scrollRel) override; | |||||
}; | }; | ||||
struct TextField : OpaqueWidget { | struct TextField : OpaqueWidget { | ||||
@@ -405,36 +405,36 @@ struct TextField : OpaqueWidget { | |||||
TextField() { | TextField() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
Widget *onMouseDown(Vec pos, int button); | |||||
bool onFocusText(int codepoint); | |||||
bool onFocusKey(int scancode); | |||||
bool onFocus(); | |||||
void draw(NVGcontext *vg) override; | |||||
Widget *onMouseDown(Vec pos, int button) override; | |||||
bool onFocusText(int codepoint) override; | |||||
bool onFocusKey(int key) override; | |||||
bool onFocus() override; | |||||
void insertText(std::string newText); | void insertText(std::string newText); | ||||
virtual void onTextChange() {} | virtual void onTextChange() {} | ||||
}; | }; | ||||
struct PasswordField : TextField { | struct PasswordField : TextField { | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct ProgressBar : TransparentWidget, QuantityWidget { | struct ProgressBar : TransparentWidget, QuantityWidget { | ||||
ProgressBar() { | ProgressBar() { | ||||
box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
} | } | ||||
void draw(NVGcontext *vg); | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct Tooltip : Widget { | struct Tooltip : Widget { | ||||
void step(); | |||||
void draw(NVGcontext *vg); | |||||
void step() override; | |||||
void draw(NVGcontext *vg) override; | |||||
}; | }; | ||||
struct Scene : OpaqueWidget { | struct Scene : OpaqueWidget { | ||||
Widget *overlay = NULL; | Widget *overlay = NULL; | ||||
void setOverlay(Widget *w); | void setOverlay(Widget *w); | ||||
Menu *createMenu(); | Menu *createMenu(); | ||||
void step(); | |||||
void step() override; | |||||
}; | }; | ||||
@@ -4,7 +4,12 @@ | |||||
namespace rack { | namespace rack { | ||||
std::string gApplicationName = "VCV Rack"; | std::string gApplicationName = "VCV Rack"; | ||||
std::string gApplicationVersion = TOSTRING(VERSION); | |||||
std::string gApplicationVersion = | |||||
#ifdef VERSION | |||||
TOSTRING(VERSION); | |||||
#else | |||||
"dev"; | |||||
#endif | |||||
std::string gApiHost = "http://api.vcvrack.com"; | std::string gApiHost = "http://api.vcvrack.com"; | ||||
RackWidget *gRackWidget = NULL; | RackWidget *gRackWidget = NULL; | ||||
@@ -12,6 +12,7 @@ namespace rack { | |||||
void Knob::onDragStart() { | void Knob::onDragStart() { | ||||
guiCursorLock(); | guiCursorLock(); | ||||
dragValue = value; | |||||
randomizable = false; | randomizable = false; | ||||
} | } | ||||
@@ -19,7 +20,11 @@ void Knob::onDragMove(Vec mouseRel) { | |||||
// Drag slower if Mod | // Drag slower if Mod | ||||
if (guiIsModPressed()) | if (guiIsModPressed()) | ||||
mouseRel = mouseRel.mult(1/16.0); | mouseRel = mouseRel.mult(1/16.0); | ||||
setValue(value - KNOB_SENSITIVITY * (maxValue - minValue) * mouseRel.y); | |||||
dragValue += KNOB_SENSITIVITY * (maxValue - minValue) * -mouseRel.y; | |||||
if (snap) | |||||
setValue(roundf(dragValue)); | |||||
else | |||||
setValue(dragValue); | |||||
} | } | ||||
void Knob::onDragEnd() { | void Knob::onDragEnd() { | ||||
@@ -31,7 +36,10 @@ void Knob::onChange() { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
engineSetParamSmooth(module, paramId, value); | |||||
if (snap) | |||||
engineSetParam(module, paramId, value); | |||||
else | |||||
engineSetParamSmooth(module, paramId, value); | |||||
} | } | ||||
@@ -6,7 +6,7 @@ namespace rack { | |||||
void Light::draw(NVGcontext *vg) { | void Light::draw(NVGcontext *vg) { | ||||
float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
float oradius = radius + 40.0; | |||||
float oradius = radius + 20.0; | |||||
// Solid | // Solid | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
@@ -103,12 +103,12 @@ void ModuleWidget::disconnect() { | |||||
} | } | ||||
} | } | ||||
void ModuleWidget::initialize() { | |||||
void ModuleWidget::reset() { | |||||
for (ParamWidget *param : params) { | for (ParamWidget *param : params) { | ||||
param->setValue(param->defaultValue); | param->setValue(param->defaultValue); | ||||
} | } | ||||
if (module) { | if (module) { | ||||
module->initialize(); | |||||
module->reset(); | |||||
} | } | ||||
} | } | ||||
@@ -170,7 +170,7 @@ Widget *ModuleWidget::onHoverKey(Vec pos, int key) { | |||||
switch (key) { | switch (key) { | ||||
case GLFW_KEY_I: | case GLFW_KEY_I: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
initialize(); | |||||
reset(); | |||||
return this; | return this; | ||||
} | } | ||||
break; | break; | ||||
@@ -206,35 +206,35 @@ void ModuleWidget::onDragEnd() { | |||||
struct DisconnectMenuItem : MenuItem { | struct DisconnectMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() { | |||||
void onAction() override { | |||||
moduleWidget->disconnect(); | moduleWidget->disconnect(); | ||||
} | } | ||||
}; | }; | ||||
struct InitializeMenuItem : MenuItem { | |||||
struct ResetMenuItem : MenuItem { | |||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() { | |||||
moduleWidget->initialize(); | |||||
void onAction() override { | |||||
moduleWidget->reset(); | |||||
} | } | ||||
}; | }; | ||||
struct RandomizeMenuItem : MenuItem { | struct RandomizeMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() { | |||||
void onAction() override { | |||||
moduleWidget->randomize(); | moduleWidget->randomize(); | ||||
} | } | ||||
}; | }; | ||||
struct CloneMenuItem : MenuItem { | struct CloneMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() { | |||||
void onAction() override { | |||||
gRackWidget->cloneModule(moduleWidget); | gRackWidget->cloneModule(moduleWidget); | ||||
} | } | ||||
}; | }; | ||||
struct DeleteMenuItem : MenuItem { | struct DeleteMenuItem : MenuItem { | ||||
ModuleWidget *moduleWidget; | ModuleWidget *moduleWidget; | ||||
void onAction() { | |||||
void onAction() override { | |||||
gRackWidget->deleteModule(moduleWidget); | gRackWidget->deleteModule(moduleWidget); | ||||
moduleWidget->finalizeEvents(); | moduleWidget->finalizeEvents(); | ||||
delete moduleWidget; | delete moduleWidget; | ||||
@@ -248,7 +248,7 @@ Menu *ModuleWidget::createContextMenu() { | |||||
menuLabel->text = model->plugin->name + ": " + model->name; | menuLabel->text = model->plugin->name + ": " + model->name; | ||||
menu->pushChild(menuLabel); | menu->pushChild(menuLabel); | ||||
InitializeMenuItem *resetItem = new InitializeMenuItem(); | |||||
ResetMenuItem *resetItem = new ResetMenuItem(); | |||||
resetItem->text = "Initialize"; | resetItem->text = "Initialize"; | ||||
resetItem->rightText = GUI_MOD_KEY_NAME "+I"; | resetItem->rightText = GUI_MOD_KEY_NAME "+I"; | ||||
resetItem->moduleWidget = this; | resetItem->moduleWidget = this; | ||||
@@ -15,7 +15,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
Vec pos = Vec(0, 0); | Vec pos = Vec(0, 0); | ||||
struct RegisterButton : Button { | struct RegisterButton : Button { | ||||
void onAction() { | |||||
void onAction() override { | |||||
std::thread t(openBrowser, "https://vcvrack.com/"); | std::thread t(openBrowser, "https://vcvrack.com/"); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -46,7 +46,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
struct LogInButton : Button { | struct LogInButton : Button { | ||||
TextField *emailField; | TextField *emailField; | ||||
TextField *passwordField; | TextField *passwordField; | ||||
void onAction() { | |||||
void onAction() override { | |||||
std::thread t(pluginLogIn, emailField->text, passwordField->text); | std::thread t(pluginLogIn, emailField->text, passwordField->text); | ||||
t.detach(); | t.detach(); | ||||
passwordField->text = ""; | passwordField->text = ""; | ||||
@@ -63,7 +63,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += logInButton->box.size.x; | pos.x += logInButton->box.size.x; | ||||
struct StatusLabel : Label { | struct StatusLabel : Label { | ||||
void step() { | |||||
void step() override { | |||||
text = pluginGetLoginStatus(); | text = pluginGetLoginStatus(); | ||||
} | } | ||||
}; | }; | ||||
@@ -79,7 +79,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
Vec pos = Vec(0, 0); | Vec pos = Vec(0, 0); | ||||
struct ManageButton : Button { | struct ManageButton : Button { | ||||
void onAction() { | |||||
void onAction() override { | |||||
std::thread t(openBrowser, "https://vcvrack.com/"); | std::thread t(openBrowser, "https://vcvrack.com/"); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -92,7 +92,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += manageButton->box.size.x; | pos.x += manageButton->box.size.x; | ||||
struct RefreshButton : Button { | struct RefreshButton : Button { | ||||
void onAction() { | |||||
void onAction() override { | |||||
std::thread t(pluginRefresh); | std::thread t(pluginRefresh); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -106,7 +106,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += refreshButton->box.size.x; | pos.x += refreshButton->box.size.x; | ||||
struct LogOutButton : Button { | struct LogOutButton : Button { | ||||
void onAction() { | |||||
void onAction() override { | |||||
pluginLogOut(); | pluginLogOut(); | ||||
} | } | ||||
}; | }; | ||||
@@ -125,7 +125,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
Vec pos = Vec(0, 0); | Vec pos = Vec(0, 0); | ||||
struct DownloadProgressBar : ProgressBar { | struct DownloadProgressBar : ProgressBar { | ||||
void step() { | |||||
void step() override { | |||||
label = "Downloading"; | label = "Downloading"; | ||||
std::string name = pluginGetDownloadName(); | std::string name = pluginGetDownloadName(); | ||||
if (name != "") | if (name != "") | ||||
@@ -142,7 +142,7 @@ PluginManagerWidget::PluginManagerWidget() { | |||||
pos.x += downloadProgress->box.size.x; | pos.x += downloadProgress->box.size.x; | ||||
// struct CancelButton : Button { | // struct CancelButton : Button { | ||||
// void onAction() { | |||||
// void onAction() override { | |||||
// pluginCancelDownload(); | // pluginCancelDownload(); | ||||
// } | // } | ||||
// }; | // }; | ||||
@@ -86,7 +86,7 @@ Widget *RackScene::onHoverKey(Vec pos, int key) { | |||||
switch (key) { | switch (key) { | ||||
case GLFW_KEY_N: | case GLFW_KEY_N: | ||||
if (guiIsModPressed() && !guiIsShiftPressed()) { | if (guiIsModPressed() && !guiIsShiftPressed()) { | ||||
gRackWidget->clear(); | |||||
gRackWidget->reset(); | |||||
return this; | return this; | ||||
} | } | ||||
break; | break; | ||||
@@ -38,6 +38,11 @@ void RackWidget::clear() { | |||||
lastPath = ""; | lastPath = ""; | ||||
} | } | ||||
void RackWidget::reset() { | |||||
clear(); | |||||
loadPatch(assetLocal("template.vcv")); | |||||
} | |||||
void RackWidget::openDialog() { | void RackWidget::openDialog() { | ||||
std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath); | std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath); | ||||
char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); | char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL); | ||||
@@ -364,7 +369,7 @@ void RackWidget::draw(NVGcontext *vg) { | |||||
struct AddModuleMenuItem : MenuItem { | struct AddModuleMenuItem : MenuItem { | ||||
Model *model; | Model *model; | ||||
Vec modulePos; | Vec modulePos; | ||||
void onAction() { | |||||
void onAction() override { | |||||
ModuleWidget *moduleWidget = model->createModuleWidget(); | ModuleWidget *moduleWidget = model->createModuleWidget(); | ||||
gRackWidget->moduleContainer->addChild(moduleWidget); | gRackWidget->moduleContainer->addChild(moduleWidget); | ||||
// Move module nearest to the mouse position | // Move module nearest to the mouse position | ||||
@@ -377,7 +382,7 @@ struct AddModuleMenuItem : MenuItem { | |||||
struct UrlItem : MenuItem { | struct UrlItem : MenuItem { | ||||
std::string url; | std::string url; | ||||
void onAction() { | |||||
void onAction() override { | |||||
std::thread t(openBrowser, url); | std::thread t(openBrowser, url); | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
@@ -386,7 +391,7 @@ struct UrlItem : MenuItem { | |||||
struct AddPluginMenuItem : MenuItem { | struct AddPluginMenuItem : MenuItem { | ||||
Plugin *plugin; | Plugin *plugin; | ||||
Vec modulePos; | Vec modulePos; | ||||
Menu *createChildMenu() { | |||||
Menu *createChildMenu() override { | |||||
// Model items | // Model items | ||||
Menu *menu = new Menu(); | Menu *menu = new Menu(); | ||||
for (Model *model : plugin->models) { | for (Model *model : plugin->models) { | ||||
@@ -5,7 +5,7 @@ namespace rack { | |||||
struct PanelBorder : TransparentWidget { | struct PanelBorder : TransparentWidget { | ||||
void draw(NVGcontext *vg) { | |||||
void draw(NVGcontext *vg) override { | |||||
NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | ||||
@@ -7,76 +7,68 @@ namespace rack { | |||||
struct NewItem : MenuItem { | struct NewItem : MenuItem { | ||||
void onAction() { | |||||
gRackWidget->clear(); | |||||
void onAction() override { | |||||
gRackWidget->reset(); | |||||
} | } | ||||
}; | }; | ||||
struct OpenItem : MenuItem { | struct OpenItem : MenuItem { | ||||
void onAction() { | |||||
void onAction() override { | |||||
gRackWidget->openDialog(); | gRackWidget->openDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct SaveItem : MenuItem { | struct SaveItem : MenuItem { | ||||
void onAction() { | |||||
void onAction() override { | |||||
gRackWidget->saveDialog(); | gRackWidget->saveDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct SaveAsItem : MenuItem { | struct SaveAsItem : MenuItem { | ||||
void onAction() { | |||||
void onAction() override { | |||||
gRackWidget->saveAsDialog(); | gRackWidget->saveAsDialog(); | ||||
} | } | ||||
}; | }; | ||||
struct QuitItem : MenuItem { | |||||
void onAction() override { | |||||
guiClose(); | |||||
} | |||||
}; | |||||
struct FileChoice : ChoiceButton { | struct FileChoice : ChoiceButton { | ||||
void onAction() { | |||||
void onAction() override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
{ | { | ||||
MenuItem *newItem = new NewItem(); | |||||
newItem->text = "New"; | |||||
newItem->rightText = GUI_MOD_KEY_NAME "+N"; | |||||
menu->pushChild(newItem); | |||||
MenuItem *openItem = new OpenItem(); | |||||
openItem->text = "Open"; | |||||
openItem->rightText = GUI_MOD_KEY_NAME "+O"; | |||||
menu->pushChild(openItem); | |||||
MenuItem *saveItem = new SaveItem(); | |||||
saveItem->text = "Save"; | |||||
saveItem->rightText = GUI_MOD_KEY_NAME "+S"; | |||||
menu->pushChild(saveItem); | |||||
MenuItem *saveAsItem = new SaveAsItem(); | |||||
saveAsItem->text = "Save as"; | |||||
saveAsItem->rightText = GUI_MOD_KEY_NAME "+Shift+S"; | |||||
menu->pushChild(saveAsItem); | |||||
menu->pushChild(construct<NewItem>(&MenuItem::text, "New", &MenuItem::rightText, GUI_MOD_KEY_NAME "+N")); | |||||
menu->pushChild(construct<OpenItem>(&MenuItem::text, "Open", &MenuItem::rightText, GUI_MOD_KEY_NAME "+O")); | |||||
menu->pushChild(construct<SaveItem>(&MenuItem::text, "Save", &MenuItem::rightText, GUI_MOD_KEY_NAME "+S")); | |||||
menu->pushChild(construct<SaveAsItem>(&MenuItem::text, "Save as", &MenuItem::rightText, GUI_MOD_KEY_NAME "+Shift+S")); | |||||
menu->pushChild(construct<QuitItem>(&MenuItem::text, "Quit", &MenuItem::rightText, GUI_MOD_KEY_NAME "+Q")); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
struct PauseItem : MenuItem { | struct PauseItem : MenuItem { | ||||
void onAction() { | |||||
void onAction() override { | |||||
gPaused = !gPaused; | gPaused = !gPaused; | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateItem : MenuItem { | struct SampleRateItem : MenuItem { | ||||
float sampleRate; | float sampleRate; | ||||
void onAction() { | |||||
void onAction() override { | |||||
engineSetSampleRate(sampleRate); | engineSetSampleRate(sampleRate); | ||||
gPaused = false; | gPaused = false; | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
void onAction() { | |||||
void onAction() override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -94,11 +86,11 @@ struct SampleRateChoice : ChoiceButton { | |||||
menu->pushChild(item); | menu->pushChild(item); | ||||
} | } | ||||
} | } | ||||
void step() { | |||||
void step() override { | |||||
if (gPaused) | if (gPaused) | ||||
text = "Paused"; | text = "Paused"; | ||||
else | else | ||||
text = stringf("%.0f Hz", gSampleRate); | |||||
text = stringf("%.0f Hz", engineGetSampleRate()); | |||||
} | } | ||||
}; | }; | ||||
@@ -65,7 +65,7 @@ struct AudioInterface : Module { | |||||
closeDevice(); | closeDevice(); | ||||
} | } | ||||
void step(); | |||||
void step() override; | |||||
void stepStream(const float *input, float *output, int numFrames); | void stepStream(const float *input, float *output, int numFrames); | ||||
int getDeviceCount(); | int getDeviceCount(); | ||||
@@ -84,7 +84,7 @@ struct AudioInterface : Module { | |||||
openDevice(deviceId, sampleRate, blockSize); | openDevice(deviceId, sampleRate, blockSize); | ||||
} | } | ||||
json_t *toJson() { | |||||
json_t *toJson() override { | |||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
if (deviceId >= 0) { | if (deviceId >= 0) { | ||||
std::string deviceName = getDeviceName(deviceId); | std::string deviceName = getDeviceName(deviceId); | ||||
@@ -95,7 +95,7 @@ struct AudioInterface : Module { | |||||
return rootJ; | return rootJ; | ||||
} | } | ||||
void fromJson(json_t *rootJ) { | |||||
void fromJson(json_t *rootJ) override { | |||||
json_t *deviceNameJ = json_object_get(rootJ, "deviceName"); | json_t *deviceNameJ = json_object_get(rootJ, "deviceName"); | ||||
if (deviceNameJ) { | if (deviceNameJ) { | ||||
std::string deviceName = json_string_value(deviceNameJ); | std::string deviceName = json_string_value(deviceNameJ); | ||||
@@ -118,7 +118,7 @@ struct AudioInterface : Module { | |||||
} | } | ||||
} | } | ||||
void initialize() { | |||||
void reset() override { | |||||
closeDevice(); | closeDevice(); | ||||
} | } | ||||
}; | }; | ||||
@@ -155,7 +155,7 @@ void AudioInterface::step() { | |||||
// Once full, sample rate convert the input | // Once full, sample rate convert the input | ||||
// inputBuffer -> SRC -> inputSrcBuffer | // inputBuffer -> SRC -> inputSrcBuffer | ||||
if (inputBuffer.full()) { | if (inputBuffer.full()) { | ||||
inputSrc.setRatio(sampleRate / gSampleRate); | |||||
inputSrc.setRatio(sampleRate / engineGetSampleRate()); | |||||
int inLen = inputBuffer.size(); | int inLen = inputBuffer.size(); | ||||
int outLen = inputSrcBuffer.capacity(); | int outLen = inputSrcBuffer.capacity(); | ||||
inputSrc.process(inputBuffer.startData(), &inLen, inputSrcBuffer.endData(), &outLen); | inputSrc.process(inputBuffer.startData(), &inLen, inputSrcBuffer.endData(), &outLen); | ||||
@@ -194,7 +194,7 @@ void AudioInterface::stepStream(const float *input, float *output, int numFrames | |||||
} | } | ||||
// Pass output through sample rate converter | // Pass output through sample rate converter | ||||
outputSrc.setRatio(gSampleRate / sampleRate); | |||||
outputSrc.setRatio(engineGetSampleRate() / sampleRate); | |||||
int inLen = numFrames; | int inLen = numFrames; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process(inputFrames, &inLen, outputBuffer.endData(), &outLen); | outputSrc.process(inputFrames, &inLen, outputBuffer.endData(), &outLen); | ||||
@@ -326,14 +326,14 @@ void AudioInterface::closeDevice() { | |||||
struct AudioItem : MenuItem { | struct AudioItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
int deviceId; | int deviceId; | ||||
void onAction() { | |||||
void onAction() override { | |||||
audioInterface->setDeviceId(deviceId); | audioInterface->setDeviceId(deviceId); | ||||
} | } | ||||
}; | }; | ||||
struct AudioChoice : ChoiceButton { | struct AudioChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() { | |||||
void onAction() override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -354,7 +354,7 @@ struct AudioChoice : ChoiceButton { | |||||
menu->pushChild(audioItem); | menu->pushChild(audioItem); | ||||
} | } | ||||
} | } | ||||
void step() { | |||||
void step() override { | |||||
std::string name = audioInterface->getDeviceName(audioInterface->deviceId); | std::string name = audioInterface->getDeviceName(audioInterface->deviceId); | ||||
text = ellipsize(name, 24); | text = ellipsize(name, 24); | ||||
} | } | ||||
@@ -364,14 +364,14 @@ struct AudioChoice : ChoiceButton { | |||||
struct SampleRateItem : MenuItem { | struct SampleRateItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
float sampleRate; | float sampleRate; | ||||
void onAction() { | |||||
void onAction() override { | |||||
audioInterface->setSampleRate(sampleRate); | audioInterface->setSampleRate(sampleRate); | ||||
} | } | ||||
}; | }; | ||||
struct SampleRateChoice : ChoiceButton { | struct SampleRateChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() { | |||||
void onAction() override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -386,7 +386,7 @@ struct SampleRateChoice : ChoiceButton { | |||||
menu->pushChild(item); | menu->pushChild(item); | ||||
} | } | ||||
} | } | ||||
void step() { | |||||
void step() override { | |||||
this->text = stringf("%.0f Hz", audioInterface->sampleRate); | this->text = stringf("%.0f Hz", audioInterface->sampleRate); | ||||
} | } | ||||
}; | }; | ||||
@@ -395,14 +395,14 @@ struct SampleRateChoice : ChoiceButton { | |||||
struct BlockSizeItem : MenuItem { | struct BlockSizeItem : MenuItem { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
int blockSize; | int blockSize; | ||||
void onAction() { | |||||
void onAction() override { | |||||
audioInterface->setBlockSize(blockSize); | audioInterface->setBlockSize(blockSize); | ||||
} | } | ||||
}; | }; | ||||
struct BlockSizeChoice : ChoiceButton { | struct BlockSizeChoice : ChoiceButton { | ||||
AudioInterface *audioInterface; | AudioInterface *audioInterface; | ||||
void onAction() { | |||||
void onAction() override { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
@@ -417,7 +417,7 @@ struct BlockSizeChoice : ChoiceButton { | |||||
menu->pushChild(item); | menu->pushChild(item); | ||||
} | } | ||||
} | } | ||||
void step() { | |||||
void step() override { | |||||
this->text = stringf("%d", audioInterface->blockSize); | this->text = stringf("%d", audioInterface->blockSize); | ||||
} | } | ||||
}; | }; | ||||
@@ -10,17 +10,17 @@ struct ModuleResizeHandle : Widget { | |||||
ModuleResizeHandle() { | ModuleResizeHandle() { | ||||
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | ||||
} | } | ||||
Widget *onMouseDown(Vec pos, int button) { | |||||
Widget *onMouseDown(Vec pos, int button) override { | |||||
if (button == 0) | if (button == 0) | ||||
return this; | return this; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
void onDragStart() { | |||||
void onDragStart() override { | |||||
assert(parent); | assert(parent); | ||||
originalWidth = parent->box.size.x; | originalWidth = parent->box.size.x; | ||||
totalX = 0.0; | totalX = 0.0; | ||||
} | } | ||||
void onDragMove(Vec mouseRel) { | |||||
void onDragMove(Vec mouseRel) override { | |||||
ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent); | ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent); | ||||
assert(m); | assert(m); | ||||
totalX += mouseRel.x; | totalX += mouseRel.x; | ||||
@@ -38,7 +38,7 @@ struct ModuleResizeHandle : Widget { | |||||
} | } | ||||
gRackWidget->requestModuleBox(m, newBox); | gRackWidget->requestModuleBox(m, newBox); | ||||
} | } | ||||
void draw(NVGcontext *vg) { | |||||
void draw(NVGcontext *vg) override { | |||||
for (float x = 5.0; x <= 10.0; x += 5.0) { | for (float x = 5.0; x <= 10.0; x += 5.0) { | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
const float margin = 5.0; | const float margin = 5.0; | ||||
@@ -18,7 +18,7 @@ struct Bridge : Module { | |||||
} | } | ||||
~Bridge() { | ~Bridge() { | ||||
} | } | ||||
void step(); | |||||
void step() override; | |||||
}; | }; | ||||
@@ -22,7 +22,7 @@ struct BlankWidget : ModuleWidget { | |||||
Widget *bottomRightScrew; | Widget *bottomRightScrew; | ||||
Widget *rightHandle; | Widget *rightHandle; | ||||
BlankWidget(); | BlankWidget(); | ||||
void step(); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
void step() override; | |||||
json_t *toJson() override; | |||||
void fromJson(json_t *rootJ) override; | |||||
}; | }; |
@@ -14,7 +14,7 @@ | |||||
namespace rack { | namespace rack { | ||||
float gSampleRate; | |||||
float sampleRate; | |||||
bool gPaused = false; | bool gPaused = false; | ||||
@@ -60,7 +60,7 @@ static void engineStep() { | |||||
smoothModule = NULL; | smoothModule = NULL; | ||||
} | } | ||||
else { | else { | ||||
value += delta * lambda / gSampleRate; | |||||
value += delta * lambda / sampleRate; | |||||
smoothModule->params[smoothParamId].value = value; | smoothModule->params[smoothParamId].value = value; | ||||
} | } | ||||
} | } | ||||
@@ -97,7 +97,7 @@ static void engineRun() { | |||||
} | } | ||||
} | } | ||||
float stepTime = mutexSteps / gSampleRate; | |||||
float stepTime = mutexSteps / sampleRate; | |||||
ahead += stepTime; | ahead += stepTime; | ||||
auto currTime = std::chrono::high_resolution_clock::now(); | auto currTime = std::chrono::high_resolution_clock::now(); | ||||
const float aheadFactor = 2.0; | const float aheadFactor = 2.0; | ||||
@@ -221,12 +221,16 @@ void engineSetParamSmooth(Module *module, int paramId, float value) { | |||||
void engineSetSampleRate(float newSampleRate) { | void engineSetSampleRate(float newSampleRate) { | ||||
VIPLock vipLock(vipMutex); | VIPLock vipLock(vipMutex); | ||||
std::lock_guard<std::mutex> lock(mutex); | std::lock_guard<std::mutex> lock(mutex); | ||||
gSampleRate = newSampleRate; | |||||
sampleRate = newSampleRate; | |||||
// onSampleRateChange | // onSampleRateChange | ||||
for (Module *module : modules) { | for (Module *module : modules) { | ||||
module->onSampleRateChange(); | module->onSampleRateChange(); | ||||
} | } | ||||
} | } | ||||
float engineGetSampleRate() { | |||||
return sampleRate; | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -32,8 +32,7 @@ static json_t *settingsToJson() { | |||||
json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ); | json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ); | ||||
// sampleRate | // sampleRate | ||||
float sampleRate = gSampleRate; | |||||
json_t *sampleRateJ = json_real(sampleRate); | |||||
json_t *sampleRateJ = json_real(engineGetSampleRate()); | |||||
json_object_set_new(rootJ, "sampleRate", sampleRateJ); | json_object_set_new(rootJ, "sampleRate", sampleRateJ); | ||||
// plugLight | // plugLight | ||||