| @@ -218,6 +218,16 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||
| virtual void randomize(); | |||
| void onMouseDown(EventMouseDown &e) override; | |||
| void onChange(EventChange &e) override; | |||
| template <typename T = ParamWidget> | |||
| static T *create(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { | |||
| T *o = Widget::create<T>(pos); | |||
| o->module = module; | |||
| o->paramId = paramId; | |||
| o->setLimits(minValue, maxValue); | |||
| o->setDefaultValue(defaultValue); | |||
| return o; | |||
| } | |||
| }; | |||
| /** Implements vertical dragging behavior for ParamWidgets */ | |||
| @@ -351,6 +361,14 @@ struct ModuleLightWidget : MultiLightWidget { | |||
| Module *module = NULL; | |||
| int firstLightId; | |||
| void step() override; | |||
| template <typename T = ModuleLightWidget> | |||
| static T *create(Vec pos, Module *module, int firstLightId) { | |||
| T *o = Widget::create<T>(pos); | |||
| o->module = module; | |||
| o->firstLightId = firstLightId; | |||
| return o; | |||
| } | |||
| }; | |||
| //////////////////// | |||
| @@ -378,6 +396,24 @@ struct Port : OpaqueWidget { | |||
| void onDragDrop(EventDragDrop &e) override; | |||
| void onDragEnter(EventDragEnter &e) override; | |||
| void onDragLeave(EventDragEnter &e) override; | |||
| template <typename T = Port> | |||
| static T *createInput(Vec pos, Module *module, int portId) { | |||
| T *o = Widget::create<T>(pos); | |||
| o->type = INPUT; | |||
| o->module = module; | |||
| o->portId = portId; | |||
| return o; | |||
| } | |||
| template <typename T = Port> | |||
| static T *createOutput(Vec pos, Module *module, int portId) { | |||
| T *o = Widget::create<T>(pos); | |||
| o->type = OUTPUT; | |||
| o->module = module; | |||
| o->portId = portId; | |||
| return o; | |||
| } | |||
| }; | |||
| struct SVGPort : Port, FramebufferWidget { | |||
| @@ -33,15 +33,17 @@ Model *createModel(std::string manufacturer, std::string slug, std::string name, | |||
| return model; | |||
| } | |||
| /** Deprecated, use Widget::create<TScrew>() instead */ | |||
| template <class TScrew> | |||
| TScrew *createScrew(Vec pos) { | |||
| DEPRECATED TScrew *createScrew(Vec pos) { | |||
| TScrew *screw = new TScrew(); | |||
| screw->box.pos = pos; | |||
| return screw; | |||
| } | |||
| /** Deprecated, use ParamWidget::create<TParamWidget>() instead */ | |||
| template <class TParamWidget> | |||
| TParamWidget *createParam(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { | |||
| DEPRECATED TParamWidget *createParam(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { | |||
| TParamWidget *param = new TParamWidget(); | |||
| param->box.pos = pos; | |||
| param->module = module; | |||
| @@ -51,8 +53,9 @@ TParamWidget *createParam(Vec pos, Module *module, int paramId, float minValue, | |||
| return param; | |||
| } | |||
| /** Deprecated, use Port::createInput<TPort>() instead */ | |||
| template <class TPort> | |||
| TPort *createInput(Vec pos, Module *module, int inputId) { | |||
| DEPRECATED TPort *createInput(Vec pos, Module *module, int inputId) { | |||
| TPort *port = new TPort(); | |||
| port->box.pos = pos; | |||
| port->module = module; | |||
| @@ -61,8 +64,9 @@ TPort *createInput(Vec pos, Module *module, int inputId) { | |||
| return port; | |||
| } | |||
| /** Deprecated, use Port::createInput<TPort>() instead */ | |||
| template <class TPort> | |||
| TPort *createOutput(Vec pos, Module *module, int outputId) { | |||
| DEPRECATED TPort *createOutput(Vec pos, Module *module, int outputId) { | |||
| TPort *port = new TPort(); | |||
| port->box.pos = pos; | |||
| port->module = module; | |||
| @@ -71,8 +75,9 @@ TPort *createOutput(Vec pos, Module *module, int outputId) { | |||
| return port; | |||
| } | |||
| /** Deprecated, use ModuleLightWidget::create<TModuleLightWidget>() instead */ | |||
| template<class TModuleLightWidget> | |||
| TModuleLightWidget *createLight(Vec pos, Module *module, int firstLightId) { | |||
| DEPRECATED TModuleLightWidget *createLight(Vec pos, Module *module, int firstLightId) { | |||
| TModuleLightWidget *light = new TModuleLightWidget(); | |||
| light->box.pos = pos; | |||
| light->module = module; | |||
| @@ -271,24 +271,24 @@ inline Vec Vec::clamp(Rect bound) { | |||
| // Deprecated functions | |||
| //////////////////// | |||
| inline int DEPRECATED mini(int a, int b) {return min(a, b);} | |||
| inline int DEPRECATED maxi(int a, int b) {return max(a, b);} | |||
| inline int DEPRECATED clampi(int x, int min, int max) {return clamp(x, min, max);} | |||
| inline int DEPRECATED absi(int a) {return abs(a);} | |||
| inline int DEPRECATED eucmodi(int a, int base) {return eucmod(a, base);} | |||
| inline int DEPRECATED log2i(int n) {return log2(n);} | |||
| inline bool DEPRECATED ispow2i(int n) {return ispow2(n);} | |||
| inline float DEPRECATED absf(float x) {return abs(x);} | |||
| inline float DEPRECATED sgnf(float x) {return sgn(x);} | |||
| inline float DEPRECATED eucmodf(float a, float base) {return eucmod(a, base);} | |||
| inline bool DEPRECATED nearf(float a, float b, float epsilon = 1.0e-6f) {return isNear(a, b, epsilon);} | |||
| inline float DEPRECATED clampf(float x, float min, float max) {return clamp(x, min, max);} | |||
| inline float DEPRECATED clamp2f(float x, float min, float max) {return clamp2(x, min, max);} | |||
| inline float DEPRECATED chopf(float x, float eps) {return chop(x, eps);} | |||
| inline float DEPRECATED rescalef(float x, float xMin, float xMax, float yMin, float yMax) {return rescale(x, xMin, xMax, yMin, yMax);} | |||
| inline float DEPRECATED crossf(float a, float b, float frac) {return crossfade(a, b, frac);} | |||
| inline float DEPRECATED interpf(const float *p, float x) {return interpolateLinear(p, x);} | |||
| inline void DEPRECATED cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {return cmult(cr, ci, ar, ai, br, bi);} | |||
| DEPRECATED inline int mini(int a, int b) {return min(a, b);} | |||
| DEPRECATED inline int maxi(int a, int b) {return max(a, b);} | |||
| DEPRECATED inline int clampi(int x, int min, int max) {return clamp(x, min, max);} | |||
| DEPRECATED inline int absi(int a) {return abs(a);} | |||
| DEPRECATED inline int eucmodi(int a, int base) {return eucmod(a, base);} | |||
| DEPRECATED inline int log2i(int n) {return log2(n);} | |||
| DEPRECATED inline bool ispow2i(int n) {return ispow2(n);} | |||
| DEPRECATED inline float absf(float x) {return abs(x);} | |||
| DEPRECATED inline float sgnf(float x) {return sgn(x);} | |||
| DEPRECATED inline float eucmodf(float a, float base) {return eucmod(a, base);} | |||
| DEPRECATED inline bool nearf(float a, float b, float epsilon = 1.0e-6f) {return isNear(a, b, epsilon);} | |||
| DEPRECATED inline float clampf(float x, float min, float max) {return clamp(x, min, max);} | |||
| DEPRECATED inline float clamp2f(float x, float min, float max) {return clamp2(x, min, max);} | |||
| DEPRECATED inline float chopf(float x, float eps) {return chop(x, eps);} | |||
| DEPRECATED inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) {return rescale(x, xMin, xMax, yMin, yMax);} | |||
| DEPRECATED inline float crossf(float a, float b, float frac) {return crossfade(a, b, frac);} | |||
| DEPRECATED inline float interpf(const float *p, float x) {return interpolateLinear(p, x);} | |||
| DEPRECATED inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {return cmult(cr, ci, ar, ai, br, bi);} | |||
| } // namespace rack | |||
| @@ -139,6 +139,18 @@ struct Widget { | |||
| virtual void onAction(EventAction &e) {} | |||
| virtual void onChange(EventChange &e) {} | |||
| virtual void onZoom(EventZoom &e); | |||
| /** Helper function for creating and initializing a Widget with certain arguments (in this case just the position). | |||
| In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner. | |||
| Example: | |||
| addChild(Widget::create<SVGWidget>(Vec(0, 0))) | |||
| */ | |||
| template <typename T = Widget> | |||
| static T *create(Vec pos) { | |||
| T *o = new T(); | |||
| o->box.pos = pos; | |||
| return o; | |||
| } | |||
| }; | |||
| struct TransformWidget : Widget { | |||
| @@ -220,10 +220,10 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| addChild(panel); | |||
| } | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 0))); | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365))); | |||
| Vec margin = Vec(5, 2); | |||
| float labelHeight = 15; | |||
| @@ -241,7 +241,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| addInput(createInput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_INPUT + i)); | |||
| addInput(Port::createInput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| @@ -254,7 +254,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addInput(createInput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_INPUT + i)); | |||
| addInput(Port::createInput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| @@ -275,7 +275,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| Port *port = createOutput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_OUTPUT + i); | |||
| Port *port = Port::createOutput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_OUTPUT + i); | |||
| addOutput(port); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| @@ -289,7 +289,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addOutput(createOutput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_OUTPUT + i)); | |||
| addOutput(Port::createOutput<PJ3410Port>(Vec(xPos, yPos), module, AudioInterface::AUDIO_OUTPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| @@ -304,5 +304,5 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| addChild(audioWidget); | |||
| // Lights | |||
| addChild(createLight<SmallLight<GreenLight>>(Vec(40, 20), module, AudioInterface::ACTIVE_LIGHT)); | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, AudioInterface::ACTIVE_LIGHT)); | |||
| } | |||
| @@ -72,10 +72,10 @@ BlankWidget::BlankWidget() { | |||
| addChild(leftHandle); | |||
| addChild(rightHandle); | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||
| topRightScrew = createScrew<ScrewSilver>(Vec(box.size.x - 30, 0)); | |||
| bottomRightScrew = createScrew<ScrewSilver>(Vec(box.size.x - 30, 365)); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| topRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)); | |||
| bottomRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)); | |||
| addChild(topRightScrew); | |||
| addChild(bottomRightScrew); | |||
| } | |||
| @@ -245,10 +245,10 @@ MidiToCVWidget::MidiToCVWidget() { | |||
| float yPos = margin; | |||
| float yGap = 35; | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| { | |||
| Label *label = new Label(); | |||
| @@ -258,8 +258,8 @@ MidiToCVWidget::MidiToCVWidget() { | |||
| yPos = labelHeight * 2; | |||
| } | |||
| addParam(createParam<LEDButton>(Vec(7 * 15, labelHeight), module, MIDIToCVInterface::RESET_PARAM, 0.0, 1.0, 0.0)); | |||
| addChild(createLight<SmallLight<RedLight>>(Vec(7 * 15 + 5, labelHeight + 5), module, MIDIToCVInterface::RESET_LIGHT)); | |||
| addParam(ParamWidget::create<LEDButton>(Vec(7 * 15, labelHeight), module, MIDIToCVInterface::RESET_PARAM, 0.0, 1.0, 0.0)); | |||
| addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(7 * 15 + 5, labelHeight + 5), module, MIDIToCVInterface::RESET_LIGHT)); | |||
| std::string labels[MIDIToCVInterface::NUM_OUTPUTS] = {"1V/oct", "Gate", "Velocity", "Mod Wheel", "Pitch Wheel", "Aftertouch"}; | |||
| @@ -269,7 +269,7 @@ MidiToCVWidget::MidiToCVWidget() { | |||
| label->text = labels[i]; | |||
| addChild(label); | |||
| addOutput(createOutput<PJ3410Port>(Vec(15 * 6, yPos - 5), module, i)); | |||
| addOutput(Port::createOutput<PJ3410Port>(Vec(15 * 6, yPos - 5), module, i)); | |||
| yPos += yGap + margin; | |||
| } | |||
| @@ -279,5 +279,5 @@ MidiToCVWidget::MidiToCVWidget() { | |||
| addChild(midiWidget); | |||
| // Lights | |||
| addChild(createLight<SmallLight<GreenLight>>(Vec(40, 20), module, MIDIToCVInterface::ACTIVE_LIGHT)); | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, MIDIToCVInterface::ACTIVE_LIGHT)); | |||
| } | |||