Browse Source

Header cleanup. ModuleBrowser work.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
f967c68110
10 changed files with 101 additions and 73 deletions
  1. +1
    -1
      docs/Makefile
  2. +17
    -11
      include/component.hpp
  3. +4
    -5
      include/dsp/fft.hpp
  4. +12
    -11
      include/dsp/vumeter.hpp
  5. +2
    -2
      include/plugin/Plugin.hpp
  6. +6
    -2
      include/rack.hpp
  7. +2
    -1
      src/app/CableWidget.cpp
  8. +54
    -38
      src/app/ModuleBrowser.cpp
  9. +1
    -1
      src/plugin.cpp
  10. +2
    -1
      src/ui/List.cpp

+ 1
- 1
docs/Makefile View File

@@ -8,7 +8,7 @@ run: doxygen
http-server html http-server html


upload: doxygen upload: doxygen
rsync html/ vcvrack.com:vcvrack.com/docs/ -ruvz --delete
rsync html/ vcvrack.com:vcvrack.com/docs/ -ruz --info=progress2 --delete


clean: clean:
rm -rfv html rm -rfv html

+ 17
- 11
include/component.hpp View File

@@ -1,5 +1,11 @@
#pragma once #pragma once
#include "rack.hpp"
#include "app/SvgKnob.hpp"
#include "app/SvgSlider.hpp"
#include "app/SvgPort.hpp"
#include "app/ModuleLightWidget.hpp"
#include "app/SvgSwitch.hpp"
#include "app/SvgScrew.hpp"
#include "asset.hpp"




namespace rack { namespace rack {
@@ -294,7 +300,7 @@ struct SynthTechAlco : app::SvgKnob {
minAngle = -0.82*M_PI; minAngle = -0.82*M_PI;
maxAngle = 0.82*M_PI; maxAngle = 0.82*M_PI;
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/SynthTechAlco.svg"))); setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/SynthTechAlco.svg")));
SvgWidget *cap = new SvgWidget;
widget::SvgWidget *cap = new widget::SvgWidget;
cap->setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/SynthTechAlco_cap.svg"))); cap->setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/SynthTechAlco_cap.svg")));
addChild(cap); addChild(cap);
} }
@@ -344,8 +350,8 @@ struct BefacoSlidePot : app::SvgSlider {


struct LEDSlider : app::SvgSlider { struct LEDSlider : app::SvgSlider {
LEDSlider() { LEDSlider() {
maxHandlePos = mm2px(math::Vec(0.738, 0.738).plus(math::Vec(2, 0)));
minHandlePos = mm2px(math::Vec(0.738, 22.078).plus(math::Vec(2, 0)));
maxHandlePos = app::mm2px(math::Vec(0.738, 0.738).plus(math::Vec(2, 0)));
minHandlePos = app::mm2px(math::Vec(0.738, 22.078).plus(math::Vec(2, 0)));
setBackgroundSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/LEDSlider.svg"))); setBackgroundSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/LEDSlider.svg")));
} }
}; };
@@ -467,7 +473,7 @@ struct RGBLight : app::ModuleLightWidget {
template <typename BASE> template <typename BASE>
struct LargeLight : BASE { struct LargeLight : BASE {
LargeLight() { LargeLight() {
this->box.size = mm2px(math::Vec(5.179, 5.179));
this->box.size = app::mm2px(math::Vec(5.179, 5.179));
} }
}; };


@@ -475,7 +481,7 @@ struct LargeLight : BASE {
template <typename BASE> template <typename BASE>
struct MediumLight : BASE { struct MediumLight : BASE {
MediumLight() { MediumLight() {
this->box.size = mm2px(math::Vec(3.176, 3.176));
this->box.size = app::mm2px(math::Vec(3.176, 3.176));
} }
}; };


@@ -483,7 +489,7 @@ struct MediumLight : BASE {
template <typename BASE> template <typename BASE>
struct SmallLight : BASE { struct SmallLight : BASE {
SmallLight() { SmallLight() {
this->box.size = mm2px(math::Vec(2.176, 2.176));
this->box.size = app::mm2px(math::Vec(2.176, 2.176));
} }
}; };


@@ -491,7 +497,7 @@ struct SmallLight : BASE {
template <typename BASE> template <typename BASE>
struct TinyLight : BASE { struct TinyLight : BASE {
TinyLight() { TinyLight() {
this->box.size = mm2px(math::Vec(1.088, 1.088));
this->box.size = app::mm2px(math::Vec(1.088, 1.088));
} }
}; };


@@ -500,18 +506,18 @@ template <typename BASE>
struct LEDBezelLight : BASE { struct LEDBezelLight : BASE {
LEDBezelLight() { LEDBezelLight() {
this->bgColor = color::BLACK_TRANSPARENT; this->bgColor = color::BLACK_TRANSPARENT;
this->box.size = mm2px(math::Vec(6.0, 6.0));
this->box.size = app::mm2px(math::Vec(6.0, 6.0));
} }
}; };


/** A light to displayed over PB61303. Must add a color by subclassing or templating. /** A light to displayed over PB61303. Must add a color by subclassing or templating.
Don't add this as a child of the PB61303 itself. Instead, just place it over it as a sibling in the scene graph, offset by mm2px(math::Vec(0.5, 0.5)).
Don't add this as a child of the PB61303 itself. Instead, just place it over it as a sibling in the scene graph, offset by app::mm2px(math::Vec(0.5, 0.5)).
*/ */
template <typename BASE> template <typename BASE>
struct PB61303Light : BASE { struct PB61303Light : BASE {
PB61303Light() { PB61303Light() {
this->bgColor = color::BLACK_TRANSPARENT; this->bgColor = color::BLACK_TRANSPARENT;
this->box.size = mm2px(math::Vec(9.0, 9.0));
this->box.size = app::mm2px(math::Vec(9.0, 9.0));
} }
}; };




+ 4
- 5
include/dsp/fft.hpp View File

@@ -18,8 +18,8 @@ void alignedDelete(T *p) {
} }




/** Real-valued FFT context
Wrapper for PFFFT (https://bitbucket.org/jpommier/pffft/)
/** Real-valued FFT context.
Wrapper for [PFFFT](https://bitbucket.org/jpommier/pffft/)
`length` must be a multiple of 32. `length` must be a multiple of 32.
*/ */
struct RealFFT { struct RealFFT {
@@ -72,8 +72,7 @@ struct RealFFT {
pffft_transform_ordered(setup, input, output, NULL, PFFFT_BACKWARD); pffft_transform_ordered(setup, input, output, NULL, PFFFT_BACKWARD);
} }


/** Scales the RFFT so that
scale(IFFT(FFT(x))) = x
/** Scales the RFFT so that `scale(IFFT(FFT(x))) = x`.
*/ */
void scale(float *x) { void scale(float *x) {
float a = 1.f / length; float a = 1.f / length;
@@ -84,7 +83,7 @@ struct RealFFT {
}; };




/** Complex-valued FFT context
/** Complex-valued FFT context.
`length` must be a multiple of 16. `length` must be a multiple of 16.
*/ */
struct ComplexFFT { struct ComplexFFT {


+ 12
- 11
include/dsp/vumeter.hpp View File

@@ -6,7 +6,7 @@ namespace rack {
namespace dsp { namespace dsp {




/** Deprecated. Use VuMeter2. */
/** Deprecated. Use VuMeter2 instead. */
struct VuMeter { struct VuMeter {
/** Decibel level difference between adjacent meter lights */ /** Decibel level difference between adjacent meter lights */
float dBInterval = 3.0; float dBInterval = 3.0;
@@ -34,17 +34,18 @@ DEPRECATED typedef VuMeter VUMeter;




/** Models a VU meter with smoothing. /** Models a VU meter with smoothing.
Supports peak and RMS (root-mean-square) metering
Supports peak and RMS (root-mean-square) metering.
Usage example for a strip of lights with 3dB increments: Usage example for a strip of lights with 3dB increments:

// Update VuMeter state every frame.
vuMeter.process(deltaTime, output);
// Iterate lights every ~512 frames (less than a screen refresh).
for (int i = 0; i < 6; i++) {
float b = vuMeter.getBrightness(-3.f * (i + 1), -3.f * i);
// No need to use setSmoothBrightness() since VuMeter2 smooths the value for you.
lights[i].setBrightness(b);
}
```
// Update VuMeter state every frame.
vuMeter.process(deltaTime, output);
// Iterate lights every ~512 frames (less than a screen refresh).
for (int i = 0; i < 6; i++) {
float b = vuMeter.getBrightness(-3.f * (i + 1), -3.f * i);
// No need to use setSmoothBrightness() since VuMeter2 smooths the value for you.
lights[i].setBrightness(b);
}
```
*/ */
struct VuMeter2 { struct VuMeter2 {
enum Mode { enum Mode {


+ 2
- 2
include/plugin/Plugin.hpp View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include <jansson.h> #include <jansson.h>
#include <list>
#include <vector>




namespace rack { namespace rack {
@@ -14,7 +14,7 @@ struct Model;
// Subclass this and return a pointer to a new one when init() is called // Subclass this and return a pointer to a new one when init() is called
struct Plugin { struct Plugin {
/** A list of the models available by this plugin, add with addModel() */ /** A list of the models available by this plugin, add with addModel() */
std::list<Model*> models;
std::vector<Model*> models;
/** The file path of the plugin's directory */ /** The file path of the plugin's directory */
std::string path; std::string path;
/** OS-dependent library handle */ /** OS-dependent library handle */


+ 6
- 2
include/rack.hpp View File

@@ -1,4 +1,5 @@
#pragma once #pragma once

// Include most Rack headers for convenience // Include most Rack headers for convenience
#include "common.hpp" #include "common.hpp"
#include "math.hpp" #include "math.hpp"
@@ -11,6 +12,7 @@
#include "app.hpp" #include "app.hpp"
#include "midi.hpp" #include "midi.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "component.hpp"


#include "widget/Widget.hpp" #include "widget/Widget.hpp"
#include "widget/TransparentWidget.hpp" #include "widget/TransparentWidget.hpp"
@@ -90,9 +92,12 @@
#include "dsp/vumeter.hpp" #include "dsp/vumeter.hpp"
#include "dsp/window.hpp" #include "dsp/window.hpp"



namespace rack { namespace rack {




/** Define this macro before including this header to prevent common namespaces from being included in the main `rack::` namespace. */
#ifndef RACK_FLATTEN_NAMESPACES
// Import some namespaces for convenience // Import some namespaces for convenience
using namespace math; using namespace math;
using namespace widget; using namespace widget;
@@ -101,9 +106,8 @@ using namespace app;
using plugin::Plugin; using plugin::Plugin;
using plugin::Model; using plugin::Model;
using namespace engine; using namespace engine;

namespace component {}
using namespace component; using namespace component;
#endif




} // namespace rack } // namespace rack

+ 2
- 1
src/app/CableWidget.cpp View File

@@ -6,6 +6,7 @@
#include "app.hpp" #include "app.hpp"
#include "patch.hpp" #include "patch.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "engine/Port.hpp"




namespace rack { namespace rack {
@@ -219,7 +220,7 @@ void CableWidget::draw(const DrawArgs &args) {
float thickness = 5; float thickness = 5;


if (isComplete()) { if (isComplete()) {
Output *output = &cable->outputModule->outputs[cable->outputId];
engine::Output *output = &cable->outputModule->outputs[cable->outputId];
// Draw opaque if mouse is hovering over a connected port // Draw opaque if mouse is hovering over a connected port
if (output->channels > 1) { if (output->channels > 1) {
// Increase thickness if output port is polyphonic // Increase thickness if output port is polyphonic


+ 54
- 38
src/app/ModuleBrowser.cpp View File

@@ -79,7 +79,7 @@ struct BrowserOverlay : widget::OpaqueWidget {
}; };




static const float MODEL_BOX_ZOOM = 0.5f;
static const float MODEL_BOX_ZOOM = 1.0f;




struct ModelBox : widget::OpaqueWidget { struct ModelBox : widget::OpaqueWidget {
@@ -92,20 +92,23 @@ struct ModelBox : widget::OpaqueWidget {
bool selected = false; bool selected = false;


ModelBox() { ModelBox() {
box.size.x = 0.f;
box.size.y = std::ceil(RACK_GRID_HEIGHT * MODEL_BOX_ZOOM);
// Approximate size as 10HP before we know the actual size.
// We need a nonzero size, otherwise the parent widget will consider it not in the draw bounds, so its preview will not be lazily created.
box.size.x = 10 * RACK_GRID_WIDTH * MODEL_BOX_ZOOM;
box.size.y = RACK_GRID_HEIGHT * MODEL_BOX_ZOOM;
box.size = box.size.ceil();
} }


void setModel(plugin::Model *model) { void setModel(plugin::Model *model) {
this->model = model; this->model = model;


infoWidget = new widget::Widget; infoWidget = new widget::Widget;
infoWidget->box.size.x = 140;
infoWidget->box.size.y = box.size.y;
infoWidget->hide();
addChild(infoWidget); addChild(infoWidget);


math::Vec pos; math::Vec pos;


// Name label
ui::Label *nameLabel = new ui::Label; ui::Label *nameLabel = new ui::Label;
// nameLabel->box.size.x = infoWidget->box.size.x; // nameLabel->box.size.x = infoWidget->box.size.x;
nameLabel->box.pos = pos; nameLabel->box.pos = pos;
@@ -113,6 +116,7 @@ struct ModelBox : widget::OpaqueWidget {
infoWidget->addChild(nameLabel); infoWidget->addChild(nameLabel);
pos = nameLabel->box.getBottomLeft(); pos = nameLabel->box.getBottomLeft();


// Plugin label
ui::Label *pluginLabel = new ui::Label; ui::Label *pluginLabel = new ui::Label;
// pluginLabel->box.size.x = infoWidget->box.size.x; // pluginLabel->box.size.x = infoWidget->box.size.x;
pluginLabel->box.pos = pos; pluginLabel->box.pos = pos;
@@ -127,24 +131,23 @@ struct ModelBox : widget::OpaqueWidget {
infoWidget->addChild(descriptionLabel); infoWidget->addChild(descriptionLabel);
pos = descriptionLabel->box.getBottomLeft(); pos = descriptionLabel->box.getBottomLeft();


pos.y = infoWidget->box.size.y;
for (const std::string &tag : model->tags) {
ui::Button *tagButton = new ui::Button;
tagButton->box.size.x = infoWidget->box.size.x;
tagButton->box.pos = pos;
tagButton->box.pos.y -= tagButton->box.size.y;
tagButton->text = tag;
infoWidget->addChild(tagButton);
pos = tagButton->box.getTopLeft();
}

ui::Button *favoriteButton = new ui::Button;
favoriteButton->box.size.x = infoWidget->box.size.x;
favoriteButton->box.pos = pos;
favoriteButton->box.pos.y -= favoriteButton->box.size.y;
favoriteButton->text = "★";
infoWidget->addChild(favoriteButton);
pos = favoriteButton->box.getTopLeft();
// for (const std::string &tag : model->tags) {
// ui::Button *tagButton = new ui::Button;
// tagButton->box.size.x = infoWidget->box.size.x;
// tagButton->box.pos = pos;
// tagButton->text = tag;
// infoWidget->addChild(tagButton);
// pos = tagButton->box.getTopLeft();
// }

// // Favorite button
// ui::Button *favoriteButton = new ui::Button;
// favoriteButton->box.size.x = box.size.x;
// favoriteButton->box.pos = pos;
// favoriteButton->box.pos.y -= favoriteButton->box.size.y;
// favoriteButton->text = "★";
// addChild(favoriteButton);
// pos = favoriteButton->box.getTopLeft();
} }


void createPreview() { void createPreview() {
@@ -171,9 +174,8 @@ struct ModelBox : widget::OpaqueWidget {
zoomWidget->box.size.y = RACK_GRID_HEIGHT * MODEL_BOX_ZOOM; zoomWidget->box.size.y = RACK_GRID_HEIGHT * MODEL_BOX_ZOOM;
previewWidget->box.size.x = std::ceil(zoomWidget->box.size.x); previewWidget->box.size.x = std::ceil(zoomWidget->box.size.x);


// Reposition infoWidget
infoWidget->box.pos.x = previewWidget->box.size.x;
box.size.x = previewWidget->box.size.x + infoWidget->box.size.x;
infoWidget->box.size = previewWidget->box.size;
box.size.x = previewWidget->box.size.x;
} }


void deletePreview() { void deletePreview() {
@@ -197,6 +199,16 @@ struct ModelBox : widget::OpaqueWidget {
createPreview(); createPreview();
} }


// Draw shadow
nvgBeginPath(args.vg);
float r = 10; // Blur radius
float c = 10; // Corner radius
nvgRect(args.vg, -r, -r, box.size.x + 2*r, box.size.y + 2*r);
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.5);
NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0);
nvgFillPaint(args.vg, nvgBoxGradient(args.vg, 0, 0, box.size.x, box.size.y, c, r, shadowColor, transparentColor));
nvgFill(args.vg);

nvgScissor(args.vg, RECT_ARGS(args.clipBox)); nvgScissor(args.vg, RECT_ARGS(args.clipBox));
widget::OpaqueWidget::draw(args); widget::OpaqueWidget::draw(args);
nvgResetScissor(args.vg); nvgResetScissor(args.vg);
@@ -261,17 +273,18 @@ struct BrowserSidebar : widget::Widget {
searchField = new BrowserSearchField; searchField = new BrowserSearchField;
addChild(searchField); addChild(searchField);


// Plugin list
pluginScroll = new ui::ScrollWidget; pluginScroll = new ui::ScrollWidget;
pluginScroll->box.pos = searchField->box.getBottomLeft();
addChild(pluginScroll); addChild(pluginScroll);


pluginList = new ui::List; pluginList = new ui::List;
pluginScroll->container->addChild(pluginList); pluginScroll->container->addChild(pluginList);


std::set<std::string> pluginNames;
std::vector<std::string> pluginNames;
for (plugin::Plugin *plugin : plugin::plugins) { for (plugin::Plugin *plugin : plugin::plugins) {
pluginNames.insert(plugin->name);
pluginNames.push_back(plugin->name);
} }
std::sort(pluginNames.begin(), pluginNames.end(), string::CaseInsensitiveCompare());


for (const std::string &pluginName : pluginNames) { for (const std::string &pluginName : pluginNames) {
ui::MenuItem *item = new ui::MenuItem; ui::MenuItem *item = new ui::MenuItem;
@@ -279,8 +292,8 @@ struct BrowserSidebar : widget::Widget {
pluginList->addChild(item); pluginList->addChild(item);
} }


// Tag list
tagScroll = new ui::ScrollWidget; tagScroll = new ui::ScrollWidget;
tagScroll->box.pos = searchField->box.getBottomLeft();
addChild(tagScroll); addChild(tagScroll);


tagList = new ui::List; tagList = new ui::List;
@@ -295,11 +308,14 @@ struct BrowserSidebar : widget::Widget {


void step() override { void step() override {
searchField->box.size.x = box.size.x; searchField->box.size.x = box.size.x;
pluginScroll->box.size.y = box.size.y - searchField->box.size.y;
pluginList->box.size.x = pluginScroll->box.size.x = box.size.x / 2;
tagScroll->box.pos.x = box.size.x / 2;
tagScroll->box.size.y = box.size.y - searchField->box.size.y;
tagList->box.size.x = tagScroll->box.size.x = box.size.x / 2;
pluginScroll->box.pos = searchField->box.getBottomLeft();
pluginScroll->box.size.y = (box.size.y - searchField->box.size.y) / 2;
pluginScroll->box.size.x = box.size.x;
pluginList->box.size.x = pluginScroll->box.size.x;
tagScroll->box.pos = pluginScroll->box.getBottomLeft().floor();
tagScroll->box.size.y = (box.size.y - searchField->box.size.y) / 2;
tagScroll->box.size.x = box.size.x;
tagList->box.size.x = tagScroll->box.size.x;
widget::Widget::step(); widget::Widget::step();
} }
}; };
@@ -313,18 +329,18 @@ struct ModuleBrowser : widget::OpaqueWidget {


ModuleBrowser() { ModuleBrowser() {
sidebar = new BrowserSidebar; sidebar = new BrowserSidebar;
sidebar->box.size.x = 300;
sidebar->box.size.x = 200;
addChild(sidebar); addChild(sidebar);


modelScroll = new ui::ScrollWidget; modelScroll = new ui::ScrollWidget;
addChild(modelScroll); addChild(modelScroll);


modelMargin = new ui::MarginLayout; modelMargin = new ui::MarginLayout;
modelMargin->margin = math::Vec(20, 20);
modelMargin->margin = math::Vec(10, 10);
modelScroll->container->addChild(modelMargin); modelScroll->container->addChild(modelMargin);


modelContainer = new ui::SequentialLayout; modelContainer = new ui::SequentialLayout;
modelContainer->spacing = math::Vec(20, 20);
modelContainer->spacing = math::Vec(10, 10);
modelMargin->addChild(modelContainer); modelMargin->addChild(modelContainer);


for (plugin::Plugin *plugin : plugin::plugins) { for (plugin::Plugin *plugin : plugin::plugins) {


+ 1
- 1
src/plugin.cpp View File

@@ -527,7 +527,7 @@ Model *getModel(const std::string &pluginSlug, const std::string &modelSlug) {
} }




/** List of allowed tags in human display form.
/** List of allowed tags in human display form, alphabetized.
All tags here should be in sentence caps for display consistency. All tags here should be in sentence caps for display consistency.
However, tags are case-insensitive in plugin metadata. However, tags are case-insensitive in plugin metadata.
*/ */


+ 2
- 1
src/ui/List.cpp View File

@@ -13,8 +13,9 @@ void List::step() {
for (widget::Widget *child : children) { for (widget::Widget *child : children) {
if (!child->visible) if (!child->visible)
continue; continue;
// Increment height, set position of child
// Set position of child
child->box.pos = math::Vec(0.0, box.size.y); child->box.pos = math::Vec(0.0, box.size.y);
// Increment height
box.size.y += child->box.size.y; box.size.y += child->box.size.y;
// Resize width of child // Resize width of child
child->box.size.x = box.size.x; child->box.size.x = box.size.x;


Loading…
Cancel
Save