Browse Source

Add LEDLightSlider and other component library classes.

tags/v1.1.5
Andrew Belt 2 years ago
parent
commit
8476828452
5 changed files with 448 additions and 103 deletions
  1. +230
    -103
      include/componentlibrary.hpp
  2. +15
    -0
      include/helpers.hpp
  3. +66
    -0
      res/ComponentLibrary/LEDSliderHandle.svg
  4. +71
    -0
      res/ComponentLibrary/LEDSliderHorizontal.svg
  5. +66
    -0
      res/ComponentLibrary/LEDSliderHorizontalHandle.svg

+ 230
- 103
include/componentlibrary.hpp View File

@@ -39,6 +39,174 @@ static const NVGcolor SCHEME_PURPLE = nvgRGB(0xd5, 0x2b, 0xed);
static const NVGcolor SCHEME_LIGHT_GRAY = nvgRGB(0xe6, 0xe6, 0xe6);
static const NVGcolor SCHEME_DARK_GRAY = nvgRGB(0x17, 0x17, 0x17);


////////////////////
// Lights
////////////////////

/*
Many of these classes use CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).

To use a red light with its default base class for example, use `RedLight` or `TRedLight<>`. (They are synonymous.)

Use the `TBase` template argument if you want a different base class.
E.g. `RectangleLight<RedLight>`

Although this paradigm might seem confusing at first, it ends up being extremely simple in your plugin code and perfect for "decorating" your classes with appearance traits and behavioral properties.
For example, need a slider with a green LED? Just use

createLightParamCentered<LEDLightSlider<GreenLight>>(...)
*/

template <typename TBase = app::ModuleLightWidget>
struct TGrayModuleLightWidget : TBase {
TGrayModuleLightWidget() {
this->bgColor = nvgRGB(0x5a, 0x5a, 0x5a);
this->borderColor = nvgRGBA(0, 0, 0, 0x60);
}
};
typedef TGrayModuleLightWidget<> GrayModuleLightWidget;

template <typename TBase = GrayModuleLightWidget>
struct TRedLight : TBase {
TRedLight() {
this->addBaseColor(SCHEME_RED);
}
};
typedef TRedLight<> RedLight;

template <typename TBase = GrayModuleLightWidget>
struct TGreenLight : TBase {
TGreenLight() {
this->addBaseColor(SCHEME_GREEN);
}
};
typedef TGreenLight<> GreenLight;

template <typename TBase = GrayModuleLightWidget>
struct TYellowLight : TBase {
TYellowLight() {
this->addBaseColor(SCHEME_YELLOW);
}
};
typedef TYellowLight<> YellowLight;

template <typename TBase = GrayModuleLightWidget>
struct TBlueLight : TBase {
TBlueLight() {
this->addBaseColor(SCHEME_BLUE);
}
};
typedef TBlueLight<> BlueLight;

template <typename TBase = GrayModuleLightWidget>
struct TWhiteLight : TBase {
TWhiteLight() {
this->addBaseColor(SCHEME_WHITE);
}
};
typedef TWhiteLight<> WhiteLight;

/** Reads two adjacent lightIds, so `lightId` and `lightId + 1` must be defined */
template <typename TBase = GrayModuleLightWidget>
struct TGreenRedLight : TBase {
TGreenRedLight() {
this->addBaseColor(SCHEME_GREEN);
this->addBaseColor(SCHEME_RED);
}
};
typedef TGreenRedLight<> GreenRedLight;

template <typename TBase = GrayModuleLightWidget>
struct TRedGreenBlueLight : TBase {
TRedGreenBlueLight() {
this->addBaseColor(SCHEME_RED);
this->addBaseColor(SCHEME_GREEN);
this->addBaseColor(SCHEME_BLUE);
}
};
typedef TRedGreenBlueLight<> RedGreenBlueLight;

/** Based on the size of 5mm LEDs */
template <typename TBase>
struct LargeLight : TBase {
LargeLight() {
this->box.size = app::mm2px(math::Vec(5.179, 5.179));
}
};

/** Based on the size of 3mm LEDs */
template <typename TBase>
struct MediumLight : TBase {
MediumLight() {
this->box.size = app::mm2px(math::Vec(3.176, 3.176));
}
};

/** Based on the size of 2mm LEDs */
template <typename TBase>
struct SmallLight : TBase {
SmallLight() {
this->box.size = app::mm2px(math::Vec(2.176, 2.176));
}
};

/** Based on the size of 1mm LEDs */
template <typename TBase>
struct TinyLight : TBase {
TinyLight() {
this->box.size = app::mm2px(math::Vec(1.088, 1.088));
}
};

template <typename TBase>
struct RectangleLight : TBase {
void drawLight(const widget::Widget::DrawArgs& args) override {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, this->box.size.x, this->box.size.y);

// Background
if (this->bgColor.a > 0.0) {
nvgFillColor(args.vg, this->bgColor);
nvgFill(args.vg);
}

// Foreground
if (this->color.a > 0.0) {
nvgFillColor(args.vg, this->color);
nvgFill(args.vg);
}

// Border
if (this->borderColor.a > 0.0) {
nvgStrokeWidth(args.vg, 0.5);
nvgStrokeColor(args.vg, this->borderColor);
nvgStroke(args.vg);
}
}
};

/** A light for displaying on top of PB61303. Must add a color by subclassing or templating. */
template <typename TBase>
struct LEDBezelLight : TBase {
LEDBezelLight() {
this->bgColor = color::BLACK_TRANSPARENT;
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.
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 TBase>
struct PB61303Light : TBase {
PB61303Light() {
this->bgColor = color::BLACK_TRANSPARENT;
this->box.size = app::mm2px(math::Vec(9.0, 9.0));
}
};


////////////////////
// Knobs
////////////////////
@@ -390,134 +558,75 @@ struct LEDSliderWhite : LEDSlider {
}
};

////////////////////
// Ports
////////////////////

struct PJ301MPort : app::SvgPort {
PJ301MPort() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/PJ301M.svg")));
struct LEDSliderHorizontal : app::SvgSlider {
LEDSliderHorizontal() {
horizontal = true;
maxHandlePos = app::mm2px(math::Vec(22.078, 0.738).plus(math::Vec(0, 2)));
minHandlePos = app::mm2px(math::Vec(0.738, 0.738).plus(math::Vec(0, 2)));
setBackgroundSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/LEDSliderHorizontal.svg")));
}
};

struct PJ3410Port : app::SvgPort {
PJ3410Port() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/PJ3410.svg")));
}
};
template <typename TBase, typename TLightBase = RedLight>
struct LightSlider : TBase {
app::ModuleLightWidget* light;

struct CL1362Port : app::SvgPort {
CL1362Port() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/CL1362.svg")));
LightSlider() {
light = new RectangleLight<TLightBase>;
this->addChild(light);
}
};

////////////////////
// Lights
////////////////////

struct GrayModuleLightWidget : app::ModuleLightWidget {
GrayModuleLightWidget() {
bgColor = nvgRGB(0x5a, 0x5a, 0x5a);
borderColor = nvgRGBA(0, 0, 0, 0x60);
void setFirstLightId(int firstLightId) {
if (this->paramQuantity)
light->module = this->paramQuantity->module;
light->firstLightId = firstLightId;
}
};

struct RedLight : GrayModuleLightWidget {
RedLight() {
addBaseColor(SCHEME_RED);
}
};

struct GreenLight : GrayModuleLightWidget {
GreenLight() {
addBaseColor(SCHEME_GREEN);
}
};

struct YellowLight : GrayModuleLightWidget {
YellowLight() {
addBaseColor(SCHEME_YELLOW);
}
};

struct BlueLight : GrayModuleLightWidget {
BlueLight() {
addBaseColor(SCHEME_BLUE);
void step() override {
TBase::step();
// Move center of light to center of handle
light->box.pos = this->handle->box.pos
.plus(this->handle->box.size.div(2))
.minus(light->box.size.div(2));
}
};

struct WhiteLight : GrayModuleLightWidget {
WhiteLight() {
addBaseColor(SCHEME_WHITE);
template <typename TLightBase = RedLight>
struct LEDLightSlider : LightSlider<LEDSlider, TLightBase> {
LEDLightSlider() {
this->setHandleSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/LEDSliderHandle.svg")));
this->light->box.size = app::mm2px(math::Vec(1.524, 3.276));
}
};

/** Reads two adjacent lightIds, so `lightId` and `lightId + 1` must be defined */
struct GreenRedLight : GrayModuleLightWidget {
GreenRedLight() {
addBaseColor(SCHEME_GREEN);
addBaseColor(SCHEME_RED);
}
};

struct RedGreenBlueLight : GrayModuleLightWidget {
RedGreenBlueLight() {
addBaseColor(SCHEME_RED);
addBaseColor(SCHEME_GREEN);
addBaseColor(SCHEME_BLUE);
}
};

/** Based on the size of 5mm LEDs */
template <typename BASE>
struct LargeLight : BASE {
LargeLight() {
this->box.size = app::mm2px(math::Vec(5.179, 5.179));
template <typename TLightBase = RedLight>
struct LEDLightSliderHorizontal : LightSlider<LEDSliderHorizontal, TLightBase> {
LEDLightSliderHorizontal() {
this->setHandleSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/LEDSliderHorizontalHandle.svg")));
this->light->box.size = app::mm2px(math::Vec(3.276, 1.524));
}
};

/** Based on the size of 3mm LEDs */
template <typename BASE>
struct MediumLight : BASE {
MediumLight() {
this->box.size = app::mm2px(math::Vec(3.176, 3.176));
}
};

/** Based on the size of 2mm LEDs */
template <typename BASE>
struct SmallLight : BASE {
SmallLight() {
this->box.size = app::mm2px(math::Vec(2.176, 2.176));
}
};
////////////////////
// Ports
////////////////////

/** Based on the size of 1mm LEDs */
template <typename BASE>
struct TinyLight : BASE {
TinyLight() {
this->box.size = app::mm2px(math::Vec(1.088, 1.088));
struct PJ301MPort : app::SvgPort {
PJ301MPort() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/PJ301M.svg")));
}
};

/** A light for displaying on top of PB61303. Must add a color by subclassing or templating. */
template <typename BASE>
struct LEDBezelLight : BASE {
LEDBezelLight() {
this->bgColor = color::BLACK_TRANSPARENT;
this->box.size = app::mm2px(math::Vec(6.0, 6.0));
struct PJ3410Port : app::SvgPort {
PJ3410Port() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/PJ3410.svg")));
}
};

/** 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 app::mm2px(math::Vec(0.5, 0.5)).
*/
template <typename BASE>
struct PB61303Light : BASE {
PB61303Light() {
this->bgColor = color::BLACK_TRANSPARENT;
this->box.size = app::mm2px(math::Vec(9.0, 9.0));
struct CL1362Port : app::SvgPort {
CL1362Port() {
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/CL1362.svg")));
}
};

@@ -595,6 +704,24 @@ struct LEDBezel : app::SvgSwitch {
}
};

template <typename TLightBase = WhiteLight>
struct LEDLightBezel : LEDBezel {
app::ModuleLightWidget* light;

LEDLightBezel() {
light = new LEDBezelLight<TLightBase>;
// Move center of light to center of box
light->box.pos = box.size.div(2).minus(light->box.size.div(2));
addChild(light);
}

void setFirstLightId(int firstLightId) {
if (paramQuantity)
light->module = paramQuantity->module;
light->firstLightId = firstLightId;
}
};

struct PB61303 : app::SvgSwitch {
PB61303() {
momentary = true;


+ 15
- 0
include/helpers.hpp View File

@@ -124,6 +124,21 @@ TModuleLightWidget* createLightCentered(math::Vec pos, engine::Module* module, i
return o;
}

/** Creates a param with a light and calls setFirstLightId() on it. */
template <class TParamWidget>
TParamWidget* createLightParam(math::Vec pos, engine::Module* module, int paramId, int firstLightId) {
TParamWidget* o = createParam<TParamWidget>(pos, module, paramId);
o->setFirstLightId(firstLightId);
return o;
}

template <class TParamWidget>
TParamWidget* createLightParamCentered(math::Vec pos, engine::Module* module, int paramId, int firstLightId) {
TParamWidget* o = createParamCentered<TParamWidget>(pos, module, paramId);
o->setFirstLightId(firstLightId);
return o;
}

template <class TMenuLabel = ui::MenuLabel>
TMenuLabel * createMenuLabel(std::string text) {
TMenuLabel* o = new TMenuLabel;


+ 66
- 0
res/ComponentLibrary/LEDSliderHandle.svg View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1.52414mm"
height="4.1423802mm"
viewBox="0 0 1.52414 4.1423802"
version="1.1"
id="svg164153"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="LEDSliderHandle.svg">
<defs
id="defs164147" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.9195959"
inkscape:cx="-23.101371"
inkscape:cy="2.1230781"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0" />
<metadata
id="metadata164150">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.96512,-95.791547)">
<path
style="fill:#5c5c5c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775"
d="m 120.48926,95.791547 v 4.14238 h -1.52414 v -4.14238 z m 0,0"
id="path162650"
inkscape:connector-curvature="0" />
</g>
</svg>

+ 71
- 0
res/ComponentLibrary/LEDSliderHorizontal.svg View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="27mm"
height="7mm"
viewBox="0 0 27 7.0000001"
version="1.1"
id="svg163547"
sodipodi:docname="LEDSliderHorizontal.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<defs
id="defs163541" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="197.63783"
inkscape:cy="37.645666"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="0"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-page="true"
inkscape:snap-nodes="false"
inkscape:snap-others="false" />
<metadata
id="metadata163544">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-105.35713,-115.26781)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775"
d="m 132.35708,120.26782 h -26.9999 v -3.00002 h 26.9999 z m 0,0"
id="path159840"
inkscape:connector-curvature="0" />
</g>
</svg>

+ 66
- 0
res/ComponentLibrary/LEDSliderHorizontalHandle.svg View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="4.1423802mm"
height="1.52414mm"
viewBox="0 0 4.1423802 1.52414"
version="1.1"
id="svg164153"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="LEDSliderHandleHorizontal.svg">
<defs
id="defs164147" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.9195959"
inkscape:cx="48.871998"
inkscape:cy="-10.251291"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0" />
<metadata
id="metadata164150">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.96512,-98.409787)">
<path
style="fill:#5c5c5c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775"
d="m 123.1075,99.933583 h -4.14238 v -1.52414 h 4.14238 z m 0,0"
id="path162650"
inkscape:connector-curvature="0" />
</g>
</svg>

Loading…
Cancel
Save