| 
							- #pragma once
 - 
 - #include "rack.hpp"
 - #include "asset.hpp"
 - #include "widgets.hpp"
 - 
 - #define LCD_FONT_DIG7 "res/digital-7.ttf"
 - #define LCD_FONTSIZE 11
 - #define LCD_LETTER_SPACING 0
 - 
 - /* show values of all knobs */
 - #define DEBUG_VALUES false
 - 
 - typedef std::shared_ptr<rack::Font> TrueType;
 - using namespace rack;
 - 
 - #ifdef USE_VST2
 - #define plugin "LindenbergResearch"
 - #else
 - extern Plugin *plugin;
 - #endif // USE_VST2
 - 
 - 
 - /**
 -  * @brief Standard LRT module
 -  */
 - struct LRModule : Module {
 -     long cnt = 0;
 - 
 - 
 -     /**
 -      * @brief Overtake default constructor for module to be compatible
 -      * @param numParams
 -      * @param numInputs
 -      * @param numOutputs
 -      * @param numLights
 -      */
 -     LRModule(int numParams, int numInputs, int numOutputs, int numLights = 0) :
 -             Module(numParams, numInputs, numOutputs, numLights) {}
 - 
 - 
 -     void step() override {
 -         Module::step();
 - 
 -         // increment counter
 -         cnt++;
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Standard LRT ModuleWidget definition
 -  */
 - struct LRModuleWidget : ModuleWidget {
 -     explicit LRModuleWidget(Module *module);
 - };
 - 
 - 
 - /**
 -  * @brief Emulation of a LCD monochrome display
 -  */
 - struct LCDWidget : Label {
 - 
 -     enum LCDType {
 -         NUMERIC,
 -         TEXT,
 -         LIST
 -     };
 - 
 -     TrueType ttfLCDDig7;
 -     float fontsize;
 - 
 -     LCDType type;
 - 
 -     NVGcolor fg;
 -     NVGcolor bg;
 - 
 -     bool active = true;
 -     float value = 0.0;
 -     unsigned char length = 0;
 -     std::string format;
 -     std::vector<std::string> items;
 - 
 -     std::string s1;
 -     std::string s2;
 - 
 -     /**
 -      * @brief Constructor
 -      */
 -     LCDWidget(NVGcolor fg, unsigned char length, std::string format, LCDType type, float fontsize = LCD_FONTSIZE);
 - 
 -     /**
 -      * @brief Draw LCD display
 -      * @param vg
 -      */
 -     void draw(NVGcontext *vg) override;
 - 
 - 
 -     inline void addItem(std::string name) {
 -         items.push_back(name);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Indicator for control voltages on knobs
 -  */
 - struct Indicator {
 -     static constexpr float OVERFLOW_THRESHOLD = 0.01f;
 - 
 -     /** flag to control drawing */
 -     bool active = false;
 - 
 -     /** color of indicator */
 -     NVGcolor normalColor = nvgRGBA(0x00, 0x00, 0x00, 0xBB);
 -     NVGcolor overflowColor = nvgRGBA(0xBB, 0x00, 0x00, 0xBB);
 - 
 -     /** radius from middle */
 -     float distance;
 - 
 -     /** normalized control voltage. must between [0..1] */
 -     float cv = 0.f;
 - 
 -     /** draw angle */
 -     float angle;
 -     float angle2;
 - 
 -     /** middle of parent */
 -     Vec middle;
 - 
 - 
 -     /**
 -      * @brief Init indicator
 -      * @param distance Radius viewed from the middle
 -      * @param angle Angle of active knob area
 -      */
 -     Indicator(float distance, float angle) {
 -         Indicator::distance = distance;
 -         Indicator::angle = angle;
 - 
 -         /** for optimization */
 -         angle2 = 2 * angle;
 -     }
 - 
 - 
 -     /**
 -      * @brief Draw routine for cv indicator
 -      * @param vg
 -      */
 -     void draw(NVGcontext *vg);
 - 
 - };
 - 
 - 
 - /**
 -  * @brief Standard LR Shadow
 -  */
 - struct LRShadow {
 - private:
 -     Rect box;
 -     float size = 0.65;
 -     float strength = 1.f;
 - 
 -     /** shadow shift */
 -     Vec shadowPos = Vec(3, 5);
 - public:
 -     /**
 -      * @brief Set the new offset of the shadow gradient
 -      * @param x
 -      * @param y
 -      */
 -     void setShadowPosition(float x, float y) {
 -         shadowPos = Vec(x, y);
 -     }
 - 
 - 
 -     void setBox(const Rect &box);
 -     void setSize(float size);
 -     void setStrength(float strength);
 - 
 -     /**
 -     * @brief Draw shadow for circular knobs
 -     * @param vg NVGcontext
 -     * @param strength Alpha value of outside gradient
 -     * @param size Outer size
 -     * @param shift XY Offset shift from middle
 -     */
 -     void drawShadow(NVGcontext *vg, float strength, float size);
 - 
 -     void draw(NVGcontext *vg);
 - };
 - 
 - 
 - /**
 -  * @brief The base of all knobs used in LR panels, includes a indicator
 -  */
 - struct LRKnob : SVGKnob {
 - private:
 -     static constexpr float ANGLE = 0.83f;
 - 
 -     /** setup indicator with default values */
 -     Indicator idc = Indicator(15.f, ANGLE);
 - 
 -     bool debug = DEBUG_VALUES;
 -     TrueType font;
 - 
 -     /** snap mode */
 -     bool snap = false;
 -     /** position to snap */
 -     float snapAt = 0.0f;
 -     /** snap sensitivity */
 -     float snapSens = 0.1;
 - 
 - protected:
 -     /** shader */
 -     LRShadow shadow = LRShadow();
 - 
 - 
 - public:
 -     /**
 -      * @brief Default constructor
 -      */
 -     LRKnob() {
 -         minAngle = -ANGLE * (float) M_PI;
 -         maxAngle = ANGLE * (float) M_PI;
 - 
 -         font = Font::load(assetGlobal("res/fonts/ShareTechMono-Regular.ttf"));
 -     }
 - 
 - 
 -     /**
 -      * @brief Set the value of the indicator
 -      * @param value
 -      */
 -     void setIndicatorValue(float value) {
 -         idc.cv = value;
 -     }
 - 
 - 
 -     /**
 -      * @brief Switch indicator on/off
 -      * @param active
 -      */
 -     void setIndicatorActive(bool active) {
 -         idc.active = active;
 -     }
 - 
 - 
 -     /**
 -      * @brief Get indicator state
 -      * @return
 -      */
 -     bool isIndicatorActive() {
 -         return idc.active;
 -     }
 - 
 - 
 -     /**
 -      * @brief Setup distance of indicator from middle
 -      * @param distance
 -      */
 -     void setIndicatorDistance(float distance) {
 -         idc.distance = distance;
 -     }
 - 
 - 
 -     /**
 -      * @brief Hook into setSVG() method to setup box dimensions correct for indicator
 -      * @param svg
 -      */
 -     void setSVG(std::shared_ptr<SVG> svg) {
 -         SVGKnob::setSVG(svg);
 - 
 -         /** inherit dimensions after loaded svg */
 -         idc.middle = Vec(box.size.x / 2, box.size.y / 2);
 -         shadow.setBox(box);
 -     }
 - 
 - 
 -     /**
 -      * @brief Creates a new instance of a LRKnob child
 -      * @tparam TParamWidget Subclass of LRKnob
 -      * @param pos Position
 -      * @param module Module pointer
 -      * @param paramId Parameter ID
 -      * @param minValue Min
 -      * @param maxValue Max
 -      * @param defaultValue Default
 -      * @return Pointer to new subclass of LRKnob
 -      */
 -     template<class TParamWidget>
 -     static TParamWidget *create(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) {
 -         auto *param = new TParamWidget();
 -         param->box.pos = pos;
 -         param->module = module;
 -         param->paramId = paramId;
 -         param->setLimits(minValue, maxValue);
 -         param->setDefaultValue(defaultValue);
 -         return param;
 -     }
 - 
 - 
 -     /**
 -      * @brief Draw knob
 -      * @param vg
 -      */
 -     void draw(NVGcontext *vg) override {
 -         /** shadow */
 -         shadow.draw(vg);
 - 
 -         /** component */
 -         FramebufferWidget::draw(vg);
 - 
 - /*
 -         nvgBeginPath(vg);
 -         nvgRect(vg, -30, -30, box.size.x + 60, box.size.y + 60);
 - 
 -         NVGcolor icol = nvgRGBAf(0.0f, 0.0f, 0.0f, 0.3f);
 -         NVGcolor ocol = nvgRGBAf(0.0f, 0.0f, 0.0f, 0.0f);;
 - 
 -         NVGpaint paint = nvgRadialGradient(vg, box.size.x / 2, box.size.y / 2,
 -                                            0.f, box.size.x /2.f * 0.9f, icol, ocol);
 -         nvgFillPaint(vg, paint);
 -         nvgFill(vg);*/
 - 
 -         /** indicator */
 -         idc.draw(vg);
 - 
 -         if (debug) {
 -             auto text = stringf("%4.2f", value);
 -             nvgFontSize(vg, 15);
 -             nvgFontFaceId(vg, font->handle);
 - 
 -             nvgFillColor(vg, nvgRGBAf(1.f, 1.f, 1.0f, 1.0f));
 -             nvgText(vg, box.size.x - 5, box.size.y + 10, text.c_str(), NULL);
 -         }
 - 
 - 
 -     }
 - 
 - 
 -     /**
 -      * @brief Setup knob snapping
 -      * @param position
 -      * @param sensitivity
 -      */
 -     void setSnap(float position, float sensitivity) {
 -         snap = true;
 -         snapSens = sensitivity;
 -         snapAt = position;
 -     }
 - 
 - 
 -     /**
 -      * @brief Remove knob snaping
 -      */
 -     void unsetSnap() {
 -         snap = false;
 -     }
 - 
 - 
 -     /**
 -      * @brief Snapping mode for knobs
 -      * @param e
 -      */
 -     void onChange(EventChange &e) override {
 -         // if the value still inside snap-tolerance keep the value zero
 -         if (snap && value > -snapSens + snapAt && value < snapSens + snapAt) value = 0;
 -         SVGKnob::onChange(e);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Quantize position to odd numbers to simulate a toggle switch
 -  */
 - struct LRToggleKnob : LRKnob {
 -     LRToggleKnob(float length = 0.5f) {
 -         //TODO: parametrize start and end angle
 -         minAngle = -0.666666f * (float) M_PI;
 -         maxAngle = length * (float) M_PI;
 - 
 -         setSVG(SVG::load(assetPlugin(plugin, "res/ToggleKnob.svg")));
 -         shadow.setShadowPosition(3, 4);
 - 
 -         shadow.setStrength(1.2f);
 -         shadow.setSize(0.7f);
 - 
 -         speed = 2.f;
 -     }
 - 
 - 
 -     void onChange(EventChange &e) override {
 -         value = round(value);
 -         SVGKnob::onChange(e);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Quantize position to odd numbers to simulate a toggle switch
 -  */
 - struct LRMiddleIncremental : LRKnob {
 -     LRMiddleIncremental(float length = 0.5f) {
 -         minAngle = -length * (float) M_PI;
 -         maxAngle = length * (float) M_PI;
 - 
 -         setSVG(SVG::load(assetPlugin(plugin, "res/MiddleIncremental.svg")));
 -         shadow.setShadowPosition(3, 4);
 - 
 -         shadow.setStrength(1.2f);
 -         shadow.setSize(0.7f);
 - 
 -         speed = 3.f;
 -     }
 - 
 - 
 -     void onChange(EventChange &e) override {
 - 
 -         value = lround(value);
 - 
 -         //value = round(value);
 -         SVGKnob::onChange(e);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief LR Big Knob
 -  */
 - struct LRBigKnob : LRKnob {
 -     LRBigKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/BigKnob.svg")));
 -         setIndicatorDistance(15);
 -         shadow.setShadowPosition(5, 6);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief LR Middle Knob
 -  */
 - struct LRMiddleKnob : LRKnob {
 -     LRMiddleKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/MiddleKnob.svg")));
 -         setIndicatorDistance(12);
 -         shadow.setShadowPosition(4, 4);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief LR Small Knob
 -  */
 - struct LRSmallKnob : LRKnob {
 -     LRSmallKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/SmallKnob.svg")));
 -         shadow.setShadowPosition(3, 3);
 -         setSnap(0.0f, 0.03f);
 - 
 - 
 -         speed = 0.9f;
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief LR Alternate Small Knob
 -  */
 - struct LRAlternateSmallKnob : LRKnob {
 -     LRAlternateSmallKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/AlternateSmallKnob.svg")));
 -         shadow.setShadowPosition(3, 3);
 -         setSnap(0.0f, 0.03f);
 - 
 - 
 -         speed = 0.9f;
 -     }
 - };
 - 
 - /**
 -  * @brief LR Middle Knob
 -  */
 - struct LRAlternateMiddleKnob : LRKnob {
 -     LRAlternateMiddleKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/AlternateMiddleKnob.svg")));
 -         setIndicatorDistance(12);
 -         shadow.setShadowPosition(4, 4);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief LR Big Knob
 -  */
 - struct LRAlternateBigKnob : LRKnob {
 -     LRAlternateBigKnob() {
 -         setSVG(SVG::load(assetPlugin(plugin, "res/AlternateBigKnob.svg")));
 -         setIndicatorDistance(15);
 -         shadow.setShadowPosition(5, 6);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Alternative IO Port
 -  */
 - struct LRIOPort : SVGPort {
 - private:
 -     LRShadow shadow = LRShadow();
 - 
 - public:
 -     LRIOPort() {
 -         background->svg = SVG::load(assetPlugin(plugin, "res/IOPortB.svg"));
 -         background->wrap();
 -         box.size = background->box.size;
 - 
 -         /** inherit dimensions */
 -         shadow.setBox(box);
 -         shadow.setSize(0.50);
 -         shadow.setShadowPosition(2, 1);
 -     }
 - 
 - 
 -     /**
 -      * @brief Hook into draw method
 -      * @param vg
 -      */
 -     void draw(NVGcontext *vg) override {
 -         shadow.draw(vg);
 -         SVGPort::draw(vg);
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Alternative IO Port
 -  */
 - struct LRIOPortC : SVGPort {
 - private:
 -     LRShadow shadow = LRShadow();
 - 
 - public:
 -     LRIOPortC() {
 -         background->svg = SVG::load(assetPlugin(plugin, "res/IOPortC.svg"));
 -         background->wrap();
 -         box.size = background->box.size;
 - 
 -         /** inherit dimensions */
 -         shadow.setBox(box);
 -         shadow.setSize(0.50);
 -         shadow.setShadowPosition(2, 1);
 -     }
 - 
 - 
 -     /**
 -      * @brief Hook into draw method
 -      * @param vg
 -      */
 -     void draw(NVGcontext *vg) override {
 -         shadow.draw(vg);
 -         SVGPort::draw(vg);
 -     }
 - };
 - 
 - /**
 -  * @brief Alternative screw head A
 -  */
 - struct ScrewDarkA : SVGScrew {
 -     ScrewDarkA() {
 -         sw->svg = SVG::load(assetPlugin(plugin, "res/ScrewDark.svg"));
 -         sw->wrap();
 -         box.size = sw->box.size;
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Alternative screw head A
 -  */
 - struct ScrewLight : SVGScrew {
 -     ScrewLight() {
 -         sw->svg = SVG::load(assetPlugin(plugin, "res/ScrewLight.svg"));
 -         sw->wrap();
 -         box.size = sw->box.size;
 -     }
 - };
 - 
 - /**
 -  * @brief Custom switch based on original Rack files
 -  */
 - struct LRSwitch : SVGSwitch, ToggleSwitch {
 -     LRSwitch() {
 -         addFrame(SVG::load(assetPlugin(plugin, "res/Switch0.svg")));
 -         addFrame(SVG::load(assetPlugin(plugin, "res/Switch1.svg")));
 -     }
 - };
 - 
 - 
 - /**
 -  * @brief Standard LED Redlight
 -  */
 - struct LRLight : SmallLight<ModuleLightWidget> {
 -     LRLight();
 - 
 -     void draw(NVGcontext *vg) override;
 - };
 - 
 - 
 - /**
 -  * @brief Standard LR module Panel
 -  */
 - struct LRPanel : SVGPanel {
 - private:
 -     /** margin of gradient box */
 -     static constexpr float MARGIN = 10;
 - 
 -     /** gradient colors */
 -     NVGcolor inner = nvgRGBAf(1.5f * .369f, 1.5f * 0.357f, 1.5f * 0.3333f, 0.25f);
 -     NVGcolor outer = nvgRGBAf(0.0f, 0.0f, 0.0f, 0.34f);;
 - 
 -     /** gradient offset */
 -     Vec offset = Vec(30, -50);
 - 
 - 
 - public:
 -     LRPanel();
 - 
 - 
 -     LRPanel(float x, float y) {
 -         offset.x = x;
 -         offset.y = y;
 -     }
 - 
 - 
 -     void setInner(const NVGcolor &inner);
 -     void setOuter(const NVGcolor &outer);
 -     const NVGcolor &getInner() const;
 -     const NVGcolor &getOuter() const;
 - 
 -     void draw(NVGcontext *vg) override;
 - };
 - 
 - 
 - /**
 -  * @brief Passive rotating SVG image
 -  */
 - struct SVGRotator : FramebufferWidget {
 -     TransformWidget *tw;
 -     SVGWidget *sw;
 - 
 -     /** angle to rotate per step */
 -     float angle = 0;
 -     float inc;
 - 
 - 
 -     SVGRotator();
 - 
 - 
 -     /**
 -      * @brief Factory method
 -      * @param pos Position
 -      * @param svg Pointer to SVG image
 -      * @param angle Increment angle per step
 -      */
 -     SVGRotator static *create(Vec pos, std::shared_ptr<SVG> svg, float inc) {
 -         SVGRotator *rotator = FramebufferWidget::create<SVGRotator>(pos);
 - 
 -         rotator->setSVG(svg);
 -         rotator->inc = inc;
 - 
 -         return rotator;
 -     }
 - 
 - 
 -     void setSVG(std::shared_ptr<SVG> svg);
 -     void step() override;
 - };
 
 
  |