@@ -89,8 +89,8 @@ All **source code** in this repository is licensed under [BSD-3-Clause](LICENSE. | |||
**Component Library graphics** in `res/ComponentLibrary` are licensed under [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/) by [Grayscale](http://grayscale.info/). Commercial plugins must request a commercial license to use Component Library graphics by emailing contact@vcvrack.com. | |||
**Core** panel graphics in `res/Core` are copyright © 2017 by Grayscale. You may not create derivative works of Core panels. | |||
**Core** panel graphics in `res/Core` are copyright © 2017 Grayscale. You may not create derivative works of Core panels. | |||
The **VCV logo and icon** are copyright © 2017 Andrew Belt and may not be used in derivative works. | |||
The **"VCV" brand name** is trademarked and may not be used for unofficial products. However, it is acceptable to use the phrase "for VCV Rack" for promotion of your plugin. For all other purposes, email contact@vcvrack.com. | |||
The **"VCV" name** is trademarked and may not be used for unofficial products. However, it is acceptable to use the phrase "for VCV Rack" for promotion of your plugin. For all other purposes, email contact@vcvrack.com. |
@@ -36,7 +36,7 @@ struct Module; | |||
struct Wire; | |||
struct RackWidget; | |||
struct ParamWidget; | |||
struct Parameter; | |||
struct Port; | |||
struct SVGPanel; | |||
@@ -58,14 +58,14 @@ struct ModuleWidget : OpaqueWidget { | |||
SVGPanel *panel = NULL; | |||
std::vector<Port*> inputs; | |||
std::vector<Port*> outputs; | |||
std::vector<ParamWidget*> params; | |||
std::vector<Parameter*> params; | |||
ModuleWidget(Module *module); | |||
~ModuleWidget(); | |||
/** Convenience functions for adding special widgets (calls addChild()) */ | |||
void addInput(Port *input); | |||
void addOutput(Port *output); | |||
void addParam(ParamWidget *param); | |||
void addParam(Parameter *param); | |||
void setPanel(std::shared_ptr<SVG> svg); | |||
virtual json_t *toJson(); | |||
@@ -200,16 +200,29 @@ struct SVGPanel : FramebufferWidget { | |||
}; | |||
//////////////////// | |||
// params | |||
// ParamWidgets and other components | |||
//////////////////// | |||
/** A Widget that exists on a Panel and interacts with a Module */ | |||
struct Component : OpaqueWidget { | |||
Module *module = NULL; | |||
template <typename T = Component> | |||
static T *create(Vec pos, Module *module) { | |||
T *o = new T(); | |||
o->box.pos = pos; | |||
o->module = module; | |||
return o; | |||
} | |||
}; | |||
struct CircularShadow : TransparentWidget { | |||
float blur = 0.0; | |||
void draw(NVGcontext *vg) override; | |||
}; | |||
struct ParamWidget : OpaqueWidget, QuantityWidget { | |||
Module *module = NULL; | |||
/** A Component which has control over a Param (defined in engine.hpp) */ | |||
struct Parameter : Component, QuantityWidget { | |||
int paramId; | |||
/** Used to momentarily disable value randomization | |||
To permanently disable or change randomization behavior, override the randomize() method instead of changing this. | |||
@@ -225,10 +238,9 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||
void onMouseDown(EventMouseDown &e) override; | |||
void onChange(EventChange &e) override; | |||
template <typename T = ParamWidget> | |||
template <typename T = Parameter> | |||
static T *create(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { | |||
T *o = Widget::create<T>(pos); | |||
o->module = module; | |||
T *o = Component::create<T>(pos, module); | |||
o->paramId = paramId; | |||
o->setLimits(minValue, maxValue); | |||
o->setDefaultValue(defaultValue); | |||
@@ -236,8 +248,11 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||
} | |||
}; | |||
/** Deprecated name of Parameter */ | |||
typedef Parameter ParamWidget; | |||
/** Implements vertical dragging behavior for ParamWidgets */ | |||
struct Knob : ParamWidget { | |||
struct Knob : Parameter { | |||
/** Snap to nearest integer while dragging */ | |||
bool snap = false; | |||
/** Multiplier for mouse movement to adjust knob value */ | |||
@@ -249,16 +264,16 @@ struct Knob : ParamWidget { | |||
void onDragEnd(EventDragEnd &e) override; | |||
}; | |||
struct SpriteKnob : virtual Knob, SpriteWidget { | |||
/** Deprecated */ | |||
struct SpriteKnob : Knob, SpriteWidget { | |||
int minIndex, maxIndex, spriteCount; | |||
void step() override; | |||
}; | |||
/** A knob which rotates an SVG and caches it in a framebuffer */ | |||
struct SVGKnob : virtual Knob, FramebufferWidget { | |||
struct SVGKnob : Knob, FramebufferWidget { | |||
/** Angles in radians */ | |||
float minAngle, maxAngle; | |||
/** Not owned */ | |||
TransformWidget *tw; | |||
SVGWidget *sw; | |||
@@ -268,6 +283,9 @@ struct SVGKnob : virtual Knob, FramebufferWidget { | |||
void onChange(EventChange &e) override; | |||
}; | |||
/** Behaves like a knob but linearly moves an SVGWidget between two points. | |||
Can be used for horizontal or vertical linear faders. | |||
*/ | |||
struct SVGFader : Knob, FramebufferWidget { | |||
/** Intermediate positions will be interpolated between these positions */ | |||
Vec minHandlePos, maxHandlePos; | |||
@@ -280,14 +298,9 @@ struct SVGFader : Knob, FramebufferWidget { | |||
void onChange(EventChange &e) override; | |||
}; | |||
struct Switch : ParamWidget { | |||
}; | |||
struct SVGSwitch : virtual Switch, FramebufferWidget { | |||
struct SVGSwitch : virtual Parameter, FramebufferWidget { | |||
std::vector<std::shared_ptr<SVG>> frames; | |||
/** Not owned */ | |||
SVGWidget *sw; | |||
SVGSwitch(); | |||
/** Adds an SVG file to represent the next switch position */ | |||
void addFrame(std::shared_ptr<SVG> svg); | |||
@@ -295,29 +308,33 @@ struct SVGSwitch : virtual Switch, FramebufferWidget { | |||
}; | |||
/** A switch that cycles through each mechanical position */ | |||
struct ToggleSwitch : virtual Switch { | |||
void onDragStart(EventDragStart &e) override { | |||
// Cycle through values | |||
// e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | |||
if (value >= maxValue) | |||
setValue(minValue); | |||
else | |||
setValue(value + 1.0); | |||
} | |||
struct ToggleSwitch : virtual Parameter { | |||
void onDragStart(EventDragStart &e) override; | |||
}; | |||
/** A switch that is turned on when held */ | |||
struct MomentarySwitch : virtual Switch { | |||
/** A switch that is turned on when held and turned off when released. | |||
Consider using SVGButton if the switch simply changes the state of your Module when clicked. | |||
*/ | |||
struct MomentarySwitch : virtual Parameter { | |||
/** Don't randomize state */ | |||
void randomize() override {} | |||
void onDragStart(EventDragStart &e) override { | |||
setValue(maxValue); | |||
EventAction eAction; | |||
onAction(eAction); | |||
} | |||
void onDragEnd(EventDragEnd &e) override { | |||
setValue(minValue); | |||
} | |||
void onDragStart(EventDragStart &e) override; | |||
void onDragEnd(EventDragEnd &e) override; | |||
}; | |||
/** A Component with a default (up) and active (down) state when clicked. | |||
Does not modify a Param, simply calls onAction() of a subclass. | |||
*/ | |||
struct SVGButton : Component, FramebufferWidget { | |||
Module *module = NULL; | |||
std::shared_ptr<SVG> defaultSVG; | |||
std::shared_ptr<SVG> activeSVG; | |||
SVGWidget *sw; | |||
SVGButton(); | |||
/** If `activeSVG` is NULL, `defaultSVG` is used as the active state instead. */ | |||
void setSVGs(std::shared_ptr<SVG> defaultSVG, std::shared_ptr<SVG> activeSVG); | |||
void onDragStart(EventDragStart &e) override; | |||
void onDragEnd(EventDragEnd &e) override; | |||
}; | |||
//////////////////// | |||
@@ -452,6 +452,26 @@ struct TinyLight : BASE { | |||
} | |||
}; | |||
/** A light to displayed over PB61303. Must add a color by subclassing or templating. */ | |||
template <typename BASE> | |||
struct LEDBezelLight : BASE { | |||
LEDBezelLight() { | |||
this->bgColor = COLOR_BLACK_TRANSPARENT; | |||
this->box.size = mm2px(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 mm2px(Vec(0.5, 0.5)). | |||
*/ | |||
template <typename BASE> | |||
struct PB61303Light : BASE { | |||
PB61303Light() { | |||
this->bgColor = COLOR_BLACK_TRANSPARENT; | |||
this->box.size = mm2px(Vec(9.0, 9.0)); | |||
} | |||
}; | |||
//////////////////// | |||
// Switches and Buttons | |||
@@ -515,18 +535,29 @@ struct BefacoPush : SVGSwitch, MomentarySwitch { | |||
} | |||
}; | |||
struct LEDBezel : SVGSwitch, MomentarySwitch { | |||
LEDBezel() { | |||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/LEDBezel.svg"))); | |||
} | |||
}; | |||
struct PB61303 : SVGSwitch, MomentarySwitch { | |||
PB61303() { | |||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303.svg"))); | |||
} | |||
}; | |||
struct LEDBezel : SVGSwitch, MomentarySwitch { | |||
LEDBezel() { | |||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/LEDBezel.svg"))); | |||
struct PB61303Button : SVGButton { | |||
PB61303Button() { | |||
setSVGs(SVG::load(assetGlobal("res/ComponentLibrary/PB61303.svg")), NULL); | |||
} | |||
}; | |||
struct LEDBezelButton : SVGButton { | |||
LEDBezelButton() { | |||
setSVGs(SVG::load(assetGlobal("res/ComponentLibrary/LEDBezel.svg")), NULL); | |||
} | |||
}; | |||
//////////////////// | |||
// Misc | |||
@@ -7,209 +7,17 @@ | |||
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:xlink="http://www.w3.org/1999/xlink" | |||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
width="10.000438mm" | |||
height="10.000403mm" | |||
viewBox="0 0 10.000438 10.000403" | |||
version="1.1" | |||
id="svg81475" | |||
id="svg27765" | |||
inkscape:version="0.92.2 5c3e80d, 2017-08-06" | |||
sodipodi:docname="PB61303.svg"> | |||
<defs | |||
id="defs81469"> | |||
<clipPath | |||
id="clip176"> | |||
<rect | |||
y="0" | |||
x="0" | |||
width="23" | |||
height="23" | |||
id="rect5578" /> | |||
</clipPath> | |||
<clipPath | |||
id="clip177"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="M 0.335938,0.0585938 H 22.300781 V 22.023438 H 0.335938 Z m 0,0" | |||
id="path5566" /> | |||
</clipPath> | |||
<clipPath | |||
id="clip178"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="m 11.316406,0.0585938 c -6.0625,0 -10.980468,4.9179682 -10.980468,10.9843752 0,6.0625 4.917968,10.980469 10.980468,10.980469 6.070313,0 10.988282,-4.917969 10.988282,-10.980469 0,-6.066407 -4.917969,-10.9843752 -10.988282,-10.9843752 m 0,0.5000002 c 5.785156,0 10.488282,4.703125 10.488282,10.484375 0,5.777343 -4.703126,10.480469 -10.488282,10.480469 -5.777344,0 -10.480468,-4.703126 -10.480468,-10.480469 0,-5.78125 4.703124,-10.484375 10.480468,-10.484375" | |||
id="path5569" /> | |||
</clipPath> | |||
<mask | |||
id="mask89"> | |||
<g | |||
style="filter:url(#alpha)" | |||
id="g5575"> | |||
<image | |||
y="-0.00263398" | |||
x="-0.51525402" | |||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAYAAADgKtSgAAAABmJLR0QA/wD/AP+gvaeTAAABMklEQVRIia3UuUoEQRDG8d+2432hoIIHCBqIqWAqGGiggan4CoKJYCr4Tia+hhiLmRhosGKg7Bp0r7ses85q/6Goobr6m5mqrq7pTq3Dmsm3aHbYj/SVxAsMpedGsuYXq2EgWWv9V8YxUiUxETCJwd8SZ6oklTCF0bLF2W6LFZnXLucHw1j4pzCxD6tfg2ti7XIwI1ZBQH8KNjKJP3SKL+I+k3CLAiGIv/GUWfwFE0E8epUGoFfxQrvmOQlSWQZ8vjNyMI16EOs9l1l8Ho8B19jILD6G14C6eC7LbsheWcddZ2AZ+xmEazhO/mPkb8UmrPxT/AhXfjjaAWdY+qPwAXa7JRQ4xVYPooM4wXbVDXu4wKby23IchzgXe/aNbsNTYCe94C3lNpLvwzMucVP1i7PyDvnKKY/BOBMhAAAAAElFTkSuQmCC" | |||
height="0.27702156" | |||
width="0.27702156" | |||
id="use5573" | |||
transform="rotate(-90)" /> | |||
</g> | |||
</mask> | |||
<filter | |||
id="alpha" | |||
filterUnits="objectBoundingBox" | |||
x="0" | |||
y="0" | |||
width="1" | |||
height="1"> | |||
<feColorMatrix | |||
type="matrix" | |||
in="SourceGraphic" | |||
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" | |||
id="feColorMatrix4149" /> | |||
</filter> | |||
<mask | |||
id="mask88"> | |||
<g | |||
style="filter:url(#alpha)" | |||
id="g5563" | |||
transform="scale(0.26458333)"> | |||
<rect | |||
x="0" | |||
y="0" | |||
width="3052.8701" | |||
height="3351.5" | |||
style="fill:#000000;fill-opacity:0.33000201;stroke:none" | |||
id="rect5561" /> | |||
</g> | |||
</mask> | |||
<filter | |||
id="filter81423" | |||
filterUnits="objectBoundingBox" | |||
x="0" | |||
y="0" | |||
width="1" | |||
height="1"> | |||
<feColorMatrix | |||
type="matrix" | |||
in="SourceGraphic" | |||
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" | |||
id="feColorMatrix81421" /> | |||
</filter> | |||
<clipPath | |||
id="clipPath81427"> | |||
<rect | |||
y="0" | |||
x="0" | |||
width="23" | |||
height="23" | |||
id="rect81425" /> | |||
</clipPath> | |||
<clipPath | |||
id="clipPath81431"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="M 0.335938,0.0585938 H 22.300781 V 22.023438 H 0.335938 Z m 0,0" | |||
id="path81429" /> | |||
</clipPath> | |||
<clipPath | |||
id="clipPath81435"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="m 11.316406,0.0585938 c -6.0625,0 -10.980468,4.9179682 -10.980468,10.9843752 0,6.0625 4.917968,10.980469 10.980468,10.980469 6.070313,0 10.988282,-4.917969 10.988282,-10.980469 0,-6.066407 -4.917969,-10.9843752 -10.988282,-10.9843752 m 0,0.5000002 c 5.785156,0 10.488282,4.703125 10.488282,10.484375 0,5.777343 -4.703126,10.480469 -10.488282,10.480469 -5.777344,0 -10.480468,-4.703126 -10.480468,-10.480469 0,-5.78125 4.703124,-10.484375 10.480468,-10.484375" | |||
id="path81433" /> | |||
</clipPath> | |||
<mask | |||
id="mask81441"> | |||
<g | |||
style="filter:url(#alpha)" | |||
id="g81439"> | |||
<image | |||
y="-0.00263398" | |||
x="-0.51525402" | |||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAYAAADgKtSgAAAABmJLR0QA/wD/AP+gvaeTAAABMklEQVRIia3UuUoEQRDG8d+2432hoIIHCBqIqWAqGGiggan4CoKJYCr4Tia+hhiLmRhosGKg7Bp0r7ses85q/6Goobr6m5mqrq7pTq3Dmsm3aHbYj/SVxAsMpedGsuYXq2EgWWv9V8YxUiUxETCJwd8SZ6oklTCF0bLF2W6LFZnXLucHw1j4pzCxD6tfg2ti7XIwI1ZBQH8KNjKJP3SKL+I+k3CLAiGIv/GUWfwFE0E8epUGoFfxQrvmOQlSWQZ8vjNyMI16EOs9l1l8Ho8B19jILD6G14C6eC7LbsheWcddZ2AZ+xmEazhO/mPkb8UmrPxT/AhXfjjaAWdY+qPwAXa7JRQ4xVYPooM4wXbVDXu4wKby23IchzgXe/aNbsNTYCe94C3lNpLvwzMucVP1i7PyDvnKKY/BOBMhAAAAAElFTkSuQmCC" | |||
height="0.27702156" | |||
width="0.27702156" | |||
id="use81437" | |||
transform="rotate(-90)" /> | |||
</g> | |||
</mask> | |||
<filter | |||
id="filter81445" | |||
filterUnits="objectBoundingBox" | |||
x="0" | |||
y="0" | |||
width="1" | |||
height="1"> | |||
<feColorMatrix | |||
type="matrix" | |||
in="SourceGraphic" | |||
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" | |||
id="feColorMatrix81443" /> | |||
</filter> | |||
<clipPath | |||
id="clip174"> | |||
<rect | |||
y="0" | |||
x="0" | |||
width="27" | |||
height="26" | |||
id="rect5553" /> | |||
</clipPath> | |||
<clipPath | |||
id="clip175"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="M 0.558594,0.289062 H 26.070312 V 25.800781 H 0.558594 Z m 0,0" | |||
id="path5550" /> | |||
</clipPath> | |||
<mask | |||
id="mask87"> | |||
<g | |||
style="filter:url(#alpha)" | |||
id="g5547" | |||
transform="scale(0.26458333)"> | |||
<rect | |||
x="0" | |||
y="0" | |||
width="3052.8701" | |||
height="3351.5" | |||
style="fill:#000000;fill-opacity:0.33000201;stroke:none" | |||
id="rect5545" /> | |||
</g> | |||
</mask> | |||
<filter | |||
id="filter81456" | |||
filterUnits="objectBoundingBox" | |||
x="0" | |||
y="0" | |||
width="1" | |||
height="1"> | |||
<feColorMatrix | |||
type="matrix" | |||
in="SourceGraphic" | |||
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" | |||
id="feColorMatrix81454" /> | |||
</filter> | |||
<clipPath | |||
id="clipPath81460"> | |||
<rect | |||
y="0" | |||
x="0" | |||
width="27" | |||
height="26" | |||
id="rect81458" /> | |||
</clipPath> | |||
<clipPath | |||
id="clipPath81464"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="M 0.558594,0.289062 H 26.070312 V 25.800781 H 0.558594 Z m 0,0" | |||
id="path81462" /> | |||
</clipPath> | |||
</defs> | |||
id="defs27759" /> | |||
<sodipodi:namedview | |||
id="base" | |||
pagecolor="#ffffff" | |||
@@ -217,9 +25,9 @@ | |||
borderopacity="1.0" | |||
inkscape:pageopacity="0.0" | |||
inkscape:pageshadow="2" | |||
inkscape:zoom="3.959798" | |||
inkscape:cx="-30.133384" | |||
inkscape:cy="16.667692" | |||
inkscape:zoom="2.8" | |||
inkscape:cx="-41.967543" | |||
inkscape:cy="-16.198567" | |||
inkscape:document-units="mm" | |||
inkscape:current-layer="layer1" | |||
showgrid="false" | |||
@@ -233,7 +41,7 @@ | |||
inkscape:window-y="18" | |||
inkscape:window-maximized="0" /> | |||
<metadata | |||
id="metadata81472"> | |||
id="metadata27762"> | |||
<rdf:RDF> | |||
<cc:Work | |||
rdf:about=""> | |||
@@ -248,16 +56,11 @@ | |||
inkscape:label="Layer 1" | |||
inkscape:groupmode="layer" | |||
id="layer1" | |||
transform="translate(-57.743829,-79.577179)"> | |||
transform="translate(-52.452162,-82.600989)"> | |||
<path | |||
inkscape:connector-curvature="0" | |||
id="path9091" | |||
d="m 67.744267,84.578086 c 0,2.760204 -2.239327,4.999496 -5.000907,4.999496 -2.760204,0 -4.999531,-2.239292 -4.999531,-4.999496 0,-2.761614 2.239327,-5.000907 4.999531,-5.000907 2.76158,0 5.000907,2.239293 5.000907,5.000907" | |||
style="fill:#211e1e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" /> | |||
<path | |||
id="path81613" | |||
d="m 67.244028,84.578086 c 0,2.484579 -2.014678,4.499293 -4.500668,4.499293 -2.484614,0 -4.499293,-2.014714 -4.499293,-4.499293 0,-2.485989 2.014679,-4.500668 4.499293,-4.500668 2.48599,0 4.500668,2.014679 4.500668,4.500668" | |||
style="clip-rule:nonzero;fill:#6a6868;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||
inkscape:connector-curvature="0" /> | |||
style="fill:#211e1e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277775" | |||
d="m 62.4526,87.601896 c 0,2.760204 -2.239327,4.999496 -4.999531,4.999496 -2.76158,0 -5.000907,-2.239292 -5.000907,-4.999496 0,-2.761615 2.239327,-5.000907 5.000907,-5.000907 2.760204,0 4.999531,2.239292 4.999531,5.000907" | |||
id="path26168" /> | |||
</g> | |||
</svg> |
@@ -43,6 +43,7 @@ struct QuadMIDIToCVInterface : Module { | |||
uint8_t notes[4]; | |||
bool gates[4]; | |||
bool pedal; | |||
int rotateIndex; | |||
QuadMIDIToCVInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS), heldNotes(128) { | |||
onReset(); | |||
@@ -71,6 +72,7 @@ struct QuadMIDIToCVInterface : Module { | |||
gates[i] = false; | |||
} | |||
pedal = false; | |||
rotateIndex = 0; | |||
} | |||
void pressNote(uint8_t note) { | |||
@@ -84,17 +86,23 @@ struct QuadMIDIToCVInterface : Module { | |||
// Set notes and gates | |||
switch (polyMode) { | |||
case ROTATE_MODE: { | |||
} break; | |||
case RESET_MODE: { | |||
} break; | |||
case REASSIGN_MODE: { | |||
} break; | |||
case UNISON_MODE: { | |||
case UNISON_MODE: { | |||
for (int i = 0; i < 4; i++) { | |||
notes[i] = note; | |||
gates[i] = true; | |||
} | |||
} break; | |||
default: break; | |||
} | |||
} | |||
@@ -105,18 +113,41 @@ struct QuadMIDIToCVInterface : Module { | |||
if (it != heldNotes.end()) | |||
heldNotes.erase(it); | |||
// Hold note if pedal is pressed | |||
// if (pedal) | |||
// return; | |||
// // Set last note | |||
// if (!heldNotes.empty()) { | |||
// auto it2 = heldNotes.end(); | |||
// it2--; | |||
// lastNote = *it2; | |||
// gate = true; | |||
// } | |||
// else { | |||
// gate = false; | |||
// } | |||
if (pedal) | |||
return; | |||
// Set last note | |||
switch (polyMode) { | |||
case ROTATE_MODE: { | |||
} break; | |||
case RESET_MODE: { | |||
} break; | |||
case REASSIGN_MODE: { | |||
} break; | |||
case UNISON_MODE: { | |||
if (!heldNotes.empty()) { | |||
auto it2 = heldNotes.end(); | |||
it2--; | |||
for (int i = 0; i < 4; i++) { | |||
notes[i] = *it2; | |||
gates[i] = true; | |||
} | |||
} | |||
else { | |||
for (int i = 0; i < 4; i++) { | |||
gates[i] = false; | |||
} | |||
} | |||
} break; | |||
default: break; | |||
} | |||
} | |||
void pressPedal() { | |||
@@ -34,7 +34,7 @@ void LightWidget::drawHalo(NVGcontext *vg) { | |||
nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | |||
NVGpaint paint; | |||
NVGcolor icol = colorMult(color, 0.15); | |||
NVGcolor icol = colorMult(color, 0.25); | |||
NVGcolor ocol = nvgRGB(0, 0, 0); | |||
paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | |||
nvgFillPaint(vg, paint); | |||
@@ -0,0 +1,18 @@ | |||
#include "app.hpp" | |||
namespace rack { | |||
void MomentarySwitch::onDragStart(EventDragStart &e) { | |||
setValue(maxValue); | |||
EventAction eAction; | |||
onAction(eAction); | |||
} | |||
void MomentarySwitch::onDragEnd(EventDragEnd &e) { | |||
setValue(minValue); | |||
} | |||
} // namespace rack |
@@ -5,29 +5,29 @@ | |||
namespace rack { | |||
json_t *ParamWidget::toJson() { | |||
json_t *Parameter::toJson() { | |||
json_t *rootJ = json_object(); | |||
json_object_set_new(rootJ, "paramId", json_integer(paramId)); | |||
json_object_set_new(rootJ, "value", json_real(value)); | |||
return rootJ; | |||
} | |||
void ParamWidget::fromJson(json_t *rootJ) { | |||
void Parameter::fromJson(json_t *rootJ) { | |||
json_t *valueJ = json_object_get(rootJ, "value"); | |||
if (valueJ) | |||
setValue(json_number_value(valueJ)); | |||
} | |||
void ParamWidget::reset() { | |||
void Parameter::reset() { | |||
setValue(defaultValue); | |||
} | |||
void ParamWidget::randomize() { | |||
void Parameter::randomize() { | |||
if (randomizable) | |||
setValue(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)); | |||
} | |||
void ParamWidget::onMouseDown(EventMouseDown &e) { | |||
void Parameter::onMouseDown(EventMouseDown &e) { | |||
if (e.button == 1) { | |||
setValue(defaultValue); | |||
} | |||
@@ -35,7 +35,7 @@ void ParamWidget::onMouseDown(EventMouseDown &e) { | |||
e.target = this; | |||
} | |||
void ParamWidget::onChange(EventChange &e) { | |||
void Parameter::onChange(EventChange &e) { | |||
if (!module) | |||
return; | |||
@@ -0,0 +1,32 @@ | |||
#include "app.hpp" | |||
namespace rack { | |||
SVGButton::SVGButton() { | |||
sw = new SVGWidget(); | |||
addChild(sw); | |||
} | |||
void SVGButton::setSVGs(std::shared_ptr<SVG> defaultSVG, std::shared_ptr<SVG> activeSVG) { | |||
sw->setSVG(defaultSVG); | |||
box.size = sw->box.size; | |||
this->defaultSVG = defaultSVG; | |||
this->activeSVG = activeSVG ? activeSVG : defaultSVG; | |||
} | |||
void SVGButton::onDragStart(EventDragStart &e) { | |||
EventAction eAction; | |||
onAction(eAction); | |||
sw->setSVG(activeSVG); | |||
dirty = true; | |||
} | |||
void SVGButton::onDragEnd(EventDragEnd &e) { | |||
sw->setSVG(defaultSVG); | |||
dirty = true; | |||
} | |||
} // namespace rack |
@@ -24,7 +24,7 @@ void SVGSwitch::onChange(EventChange &e) { | |||
int index = clamp((int) roundf(valueScaled), 0, frames.size() - 1); | |||
sw->setSVG(frames[index]); | |||
dirty = true; | |||
Switch::onChange(e); | |||
ParamWidget::onChange(e); | |||
} | |||
@@ -0,0 +1,17 @@ | |||
#include "app.hpp" | |||
namespace rack { | |||
void ToggleSwitch::onDragStart(EventDragStart &e) { | |||
// Cycle through values | |||
// e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3. | |||
if (value >= maxValue) | |||
setValue(minValue); | |||
else | |||
setValue(value + 1.0); | |||
} | |||
} // namespace rack |
@@ -20,7 +20,7 @@ int main(int argc, char* argv[]) { | |||
gLogFile = fopen(logFilename.c_str(), "w"); | |||
#endif | |||
info("Rack v%s", gApplicationVersion.c_str()); | |||
info("Rack %s", gApplicationVersion.c_str()); | |||
{ | |||
char *cwd = getcwd(NULL, 0); | |||