|
|
@@ -39,48 +39,85 @@ struct MotionMTR : Module { |
|
|
LIGHTS_LEN |
|
|
LIGHTS_LEN |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
dsp::VuMeter vuBar[3]; |
|
|
|
|
|
|
|
|
struct Map { |
|
|
|
|
|
float dbValue; |
|
|
|
|
|
long ledNumber; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const Map lut[20] = { |
|
|
|
|
|
{ -30.5, 1}, { -30, 2}, { -30, 3}, { -26, 4}, { -25, 5}, { -24, 6}, { -23, 7 }, { -22, 8 }, { -21, 9}, { -20, 10}, |
|
|
|
|
|
{ -19, 11}, { -18, 12}, { -16, 13}, { -14, 14}, { -12, 15}, { -10, 16}, { -8, 17}, { -6, 18}, { -4, 19}, { -2, 20} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
dsp::VuMeter2 vuBar[3]; |
|
|
|
|
|
|
|
|
const int updateLEDRate = 16; |
|
|
const int updateLEDRate = 16; |
|
|
dsp::ClockDivider sliderUpdate; |
|
|
dsp::ClockDivider sliderUpdate; |
|
|
|
|
|
|
|
|
|
|
|
bool startingUp = true; |
|
|
|
|
|
dsp::Timer startupTimer; |
|
|
|
|
|
|
|
|
|
|
|
bool break10VNormalForAudioMode = true; |
|
|
|
|
|
|
|
|
MotionMTR() { |
|
|
MotionMTR() { |
|
|
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); |
|
|
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); |
|
|
configSwitch(MODE1_PARAM, 0.f, 2.f, 0.f, "Channel 1 mode", modeLabels); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto mode1 = configSwitch(MODE1_PARAM, 0.f, 2.f, 1.f, "Channel 1 mode", modeLabels); |
|
|
|
|
|
mode1->snapEnabled = true; |
|
|
configParam(CTRL_1_PARAM, 0.f, 1.f, 0.f, "Channel 1 gain"); |
|
|
configParam(CTRL_1_PARAM, 0.f, 1.f, 0.f, "Channel 1 gain"); |
|
|
configSwitch(MODE2_PARAM, 0.f, 2.f, 0.f, "Channel 2 mode", modeLabels); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto mode2 = configSwitch(MODE2_PARAM, 0.f, 2.f, 1.f, "Channel 2 mode", modeLabels); |
|
|
|
|
|
mode2->snapEnabled = true; |
|
|
configParam(CTRL_2_PARAM, 0.f, 1.f, 0.f, "Channel 2 gain"); |
|
|
configParam(CTRL_2_PARAM, 0.f, 1.f, 0.f, "Channel 2 gain"); |
|
|
configSwitch(MODE3_PARAM, 0.f, 2.f, 0.f, "Channel 3 mode", modeLabels); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto mode3 = configSwitch(MODE3_PARAM, 0.f, 2.f, 1.f, "Channel 3 mode", modeLabels); |
|
|
|
|
|
mode3->snapEnabled = true; |
|
|
configParam(CTRL_3_PARAM, 0.f, 1.f, 0.f, "Channel 3 gain"); |
|
|
configParam(CTRL_3_PARAM, 0.f, 1.f, 0.f, "Channel 3 gain"); |
|
|
|
|
|
|
|
|
auto in1 = configInput(IN1_INPUT, "Channel 1"); |
|
|
auto in1 = configInput(IN1_INPUT, "Channel 1"); |
|
|
in1->description = "Normalled to 10V"; |
|
|
|
|
|
|
|
|
in1->description = "Normalled to 10V (except optionally in audio mode)"; |
|
|
auto in2 = configInput(IN2_INPUT, "Channel 2"); |
|
|
auto in2 = configInput(IN2_INPUT, "Channel 2"); |
|
|
in2->description = "Normalled to 10V"; |
|
|
|
|
|
|
|
|
in2->description = "Normalled to 10V (except optionally in audio mode)"; |
|
|
auto in3 = configInput(IN3_INPUT, "Channel 3"); |
|
|
auto in3 = configInput(IN3_INPUT, "Channel 3"); |
|
|
in3->description = "Normalled to 10V"; |
|
|
|
|
|
|
|
|
in3->description = "Normalled to 10V (except optionally in audio mode)"; |
|
|
|
|
|
|
|
|
configOutput(OUT1_OUTPUT, "Channel 1"); |
|
|
configOutput(OUT1_OUTPUT, "Channel 1"); |
|
|
configOutput(OUT2_OUTPUT, "Channel 2"); |
|
|
configOutput(OUT2_OUTPUT, "Channel 2"); |
|
|
configOutput(OUT3_OUTPUT, "Channel 3 (Mix)"); |
|
|
configOutput(OUT3_OUTPUT, "Channel 3 (Mix)"); |
|
|
|
|
|
|
|
|
vuBar[0].dBInterval = 3; |
|
|
|
|
|
vuBar[1].dBInterval = 3; |
|
|
|
|
|
vuBar[2].dBInterval = 3; |
|
|
|
|
|
|
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { |
|
|
|
|
|
configLight(LIGHT_1 + i * 3, string::f("%g to %g dB", lut[i - 1].dbValue, lut[i].dbValue)); |
|
|
|
|
|
configLight(LIGHT_2 + i * 3, string::f("%g to %g dB", lut[i - 1].dbValue, lut[i].dbValue)); |
|
|
|
|
|
configLight(LIGHT_3 + i * 3, string::f("%g to %g dB", lut[i - 1].dbValue, lut[i].dbValue)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
|
|
vuBar[i].mode = dsp::VuMeter2::PEAK; |
|
|
|
|
|
vuBar[i].lambda = 10.f * updateLEDRate; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// only poll EQ sliders every 16 samples |
|
|
// only poll EQ sliders every 16 samples |
|
|
sliderUpdate.setDivision(updateLEDRate); |
|
|
sliderUpdate.setDivision(updateLEDRate); |
|
|
|
|
|
// timer for startup animation |
|
|
|
|
|
startupTimer.reset(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void process(const ProcessArgs& args) override { |
|
|
|
|
|
|
|
|
void onReset(const ResetEvent& e) override { |
|
|
|
|
|
startingUp = true; |
|
|
|
|
|
startupTimer.reset(); |
|
|
|
|
|
Module::onReset(e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const float in1 = inputs[IN1_INPUT].getNormalVoltage(10.f); |
|
|
|
|
|
const float in2 = inputs[IN2_INPUT].getNormalVoltage(10.f); |
|
|
|
|
|
const float in3 = inputs[IN3_INPUT].getNormalVoltage(10.f); |
|
|
|
|
|
|
|
|
void process(const ProcessArgs& args) override { |
|
|
|
|
|
|
|
|
const LightDisplayType mode1 = (LightDisplayType) params[MODE1_PARAM].getValue(); |
|
|
const LightDisplayType mode1 = (LightDisplayType) params[MODE1_PARAM].getValue(); |
|
|
const LightDisplayType mode2 = (LightDisplayType) params[MODE2_PARAM].getValue(); |
|
|
const LightDisplayType mode2 = (LightDisplayType) params[MODE2_PARAM].getValue(); |
|
|
const LightDisplayType mode3 = (LightDisplayType) params[MODE3_PARAM].getValue(); |
|
|
const LightDisplayType mode3 = (LightDisplayType) params[MODE3_PARAM].getValue(); |
|
|
|
|
|
|
|
|
|
|
|
const float in1 = inputs[IN1_INPUT].getNormalVoltage(10.f * (mode1 != AUDIO || !break10VNormalForAudioMode)); |
|
|
|
|
|
const float in2 = inputs[IN2_INPUT].getNormalVoltage(10.f * (mode2 != AUDIO || !break10VNormalForAudioMode)); |
|
|
|
|
|
const float in3 = inputs[IN3_INPUT].getNormalVoltage(10.f * (mode3 != AUDIO || !break10VNormalForAudioMode)); |
|
|
|
|
|
|
|
|
const float out1 = in1 * params[CTRL_1_PARAM].getValue() * (mode1 == CV_INV ? -1 : +1); |
|
|
const float out1 = in1 * params[CTRL_1_PARAM].getValue() * (mode1 == CV_INV ? -1 : +1); |
|
|
const float out2 = in2 * params[CTRL_2_PARAM].getValue() * (mode2 == CV_INV ? -1 : +1); |
|
|
const float out2 = in2 * params[CTRL_2_PARAM].getValue() * (mode2 == CV_INV ? -1 : +1); |
|
|
float out3 = in3 * params[CTRL_3_PARAM].getValue() * (mode3 == CV_INV ? -1 : +1); |
|
|
float out3 = in3 * params[CTRL_3_PARAM].getValue() * (mode3 == CV_INV ? -1 : +1); |
|
|
@@ -92,7 +129,12 @@ struct MotionMTR : Module { |
|
|
out3 += out2; |
|
|
out3 += out2; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sliderUpdate.process()) { |
|
|
|
|
|
|
|
|
// special light pattern when starting up :) |
|
|
|
|
|
if (startingUp) { |
|
|
|
|
|
processStartup(args); |
|
|
|
|
|
} |
|
|
|
|
|
// otherwise (periodically) update LEDS according to value |
|
|
|
|
|
else if (sliderUpdate.process()) { |
|
|
lightsForSignal(mode1, LIGHT_1, out1, args, 0); |
|
|
lightsForSignal(mode1, LIGHT_1, out1, args, 0); |
|
|
lightsForSignal(mode2, LIGHT_2, out2, args, 1); |
|
|
lightsForSignal(mode2, LIGHT_2, out2, args, 1); |
|
|
lightsForSignal(mode3, LIGHT_3, out3, args, 2); |
|
|
lightsForSignal(mode3, LIGHT_3, out3, args, 2); |
|
|
@@ -103,57 +145,158 @@ struct MotionMTR : Module { |
|
|
outputs[OUT3_OUTPUT].setVoltage(out3); |
|
|
outputs[OUT3_OUTPUT].setVoltage(out3); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void setLightRGB(int lightId, const ProcessArgs& args, float R, float G, float B) { |
|
|
|
|
|
|
|
|
void processStartup(const ProcessArgs& args) { |
|
|
|
|
|
float time = startupTimer.process(args.sampleTime); |
|
|
|
|
|
const float ringTime = 0.4; |
|
|
|
|
|
|
|
|
|
|
|
if (time < ringTime) { |
|
|
|
|
|
int light = floor(NUM_LIGHTS_PER_DIAL * time / ringTime); |
|
|
|
|
|
setLightHSBSmooth(LIGHT_1 + 3 * light, args, 360 * time / ringTime, 1., 1.); |
|
|
|
|
|
} |
|
|
|
|
|
else if (time < 2 * ringTime) { |
|
|
|
|
|
time -= ringTime; |
|
|
|
|
|
int light = floor(NUM_LIGHTS_PER_DIAL * time / ringTime); |
|
|
|
|
|
setLightHSBSmooth(LIGHT_2 + 3 * light, args, 360 * time / ringTime, 1., 1.); |
|
|
|
|
|
} |
|
|
|
|
|
else if (time < 3 * ringTime) { |
|
|
|
|
|
time -= 2 * ringTime; |
|
|
|
|
|
int light = floor(NUM_LIGHTS_PER_DIAL * time / ringTime); |
|
|
|
|
|
setLightHSBSmooth(LIGHT_3 + 3 * light, args, 360 * time / ringTime, 1., 1.); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
startingUp = false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void setLightRGB(int lightId, float R, float G, float B) { |
|
|
|
|
|
lights[lightId + 0].setBrightness(R); |
|
|
|
|
|
lights[lightId + 1].setBrightness(G); |
|
|
|
|
|
lights[lightId + 2].setBrightness(B); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void setLightRGBSmooth(int lightId, const ProcessArgs& args, float R, float G, float B) { |
|
|
// inverse time constant for LED smoothing |
|
|
// inverse time constant for LED smoothing |
|
|
const float lambda = 10.f * updateLEDRate; |
|
|
const float lambda = 10.f * updateLEDRate; |
|
|
|
|
|
|
|
|
lights[lightId + 0].setBrightnessSmooth(R, args.sampleTime, lambda); |
|
|
lights[lightId + 0].setBrightnessSmooth(R, args.sampleTime, lambda); |
|
|
lights[lightId + 1].setBrightnessSmooth(G, args.sampleTime, lambda); |
|
|
lights[lightId + 1].setBrightnessSmooth(G, args.sampleTime, lambda); |
|
|
lights[lightId + 2].setBrightnessSmooth(B, args.sampleTime, lambda); |
|
|
lights[lightId + 2].setBrightnessSmooth(B, args.sampleTime, lambda); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// hue: 0 - 360 |
|
|
|
|
|
void setLightHSBSmooth(int lightId, const ProcessArgs& args, float H, float S, float V) { |
|
|
|
|
|
|
|
|
|
|
|
float C = S * V; |
|
|
|
|
|
float X = C * (1 - std::abs(std::fmod(H / 60.0, 2) - 1)); |
|
|
|
|
|
float m = V - C; |
|
|
|
|
|
float r, g, b; |
|
|
|
|
|
if (H >= 0 && H < 60) { |
|
|
|
|
|
r = C, g = X, b = 0; |
|
|
|
|
|
} |
|
|
|
|
|
else if (H >= 60 && H < 120) { |
|
|
|
|
|
r = X, g = C, b = 0; |
|
|
|
|
|
} |
|
|
|
|
|
else if (H >= 120 && H < 180) { |
|
|
|
|
|
r = 0, g = C, b = X; |
|
|
|
|
|
} |
|
|
|
|
|
else if (H >= 180 && H < 240) { |
|
|
|
|
|
r = 0, g = X, b = C; |
|
|
|
|
|
} |
|
|
|
|
|
else if (H >= 240 && H < 300) { |
|
|
|
|
|
r = X, g = 0, b = C; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
r = C, g = 0, b = X; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float R = (r + m); |
|
|
|
|
|
float G = (g + m); |
|
|
|
|
|
float B = (b + m); |
|
|
|
|
|
|
|
|
|
|
|
setLightRGBSmooth(lightId, args, R, G, B); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void lightsForSignal(LightDisplayType type, const LightId lightId, float signal, const ProcessArgs& args, const int channel) { |
|
|
void lightsForSignal(LightDisplayType type, const LightId lightId, float signal, const ProcessArgs& args, const int channel) { |
|
|
|
|
|
|
|
|
if (type == AUDIO) { |
|
|
if (type == AUDIO) { |
|
|
setLightRGB(lightId, args, 0.f, 1.0f, 0.f); |
|
|
|
|
|
|
|
|
setLightRGB(lightId, 0.f, 1.0f, 0.f); |
|
|
|
|
|
|
|
|
vuBar[channel].setValue(signal / 10.0f); |
|
|
|
|
|
|
|
|
vuBar[channel].process(args.sampleTime * updateLEDRate, signal / 10.f); |
|
|
|
|
|
|
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; i++) { |
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; i++) { |
|
|
const float value = vuBar[channel].getBrightness(NUM_LIGHTS_PER_DIAL - i); |
|
|
|
|
|
|
|
|
const float value = vuBar[channel].getBrightness(lut[i - 1].dbValue, lut[i].dbValue); |
|
|
if (i < 15) { |
|
|
if (i < 15) { |
|
|
// green |
|
|
// green |
|
|
setLightRGB(lightId + 3 * i, args, 0.f, value, 0.f); |
|
|
|
|
|
|
|
|
setLightRGB(lightId + 3 * i, 0.f, value, 0.f); |
|
|
} |
|
|
} |
|
|
else if (i < NUM_LIGHTS_PER_DIAL - 1) { |
|
|
else if (i < NUM_LIGHTS_PER_DIAL - 1) { |
|
|
// yellow |
|
|
// yellow |
|
|
setLightRGB(lightId + 3 * i, args, value, 0.65 * value, 0.f); |
|
|
|
|
|
|
|
|
setLightRGB(lightId + 3 * i, value, 0.65 * value, 0.f); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
// red |
|
|
// red |
|
|
setLightRGB(lightId + 3 * i, args, value, 0.f, 0.f); |
|
|
|
|
|
|
|
|
setLightRGB(lightId + 3 * i, value, 0.f, 0.f); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
setLightRGB(lightId, args, 0.82f, 0.0f, 0.82f); |
|
|
|
|
|
|
|
|
setLightRGBSmooth(lightId, args, 0.82f, 0.0f, 0.82f); |
|
|
|
|
|
|
|
|
if (signal >= 0) { |
|
|
if (signal >= 0) { |
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { |
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { |
|
|
float value = 0.5f * (signal > (10 * (i + 1.) / (NUM_LIGHTS_PER_DIAL + 1))); |
|
|
|
|
|
|
|
|
float value = (signal > (10 * (i + 1.) / (NUM_LIGHTS_PER_DIAL + 1))); |
|
|
// purple |
|
|
// purple |
|
|
setLightRGB(lightId + 3 * i, args, 0.82f * value, 0.0f, 0.82f * value); |
|
|
|
|
|
|
|
|
setLightRGBSmooth(lightId + 3 * i, args, 0.82f * value, 0.0f, 0.82f * value); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { |
|
|
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { |
|
|
float value = (signal < (-10 * (NUM_LIGHTS_PER_DIAL - i + 1.) / (NUM_LIGHTS_PER_DIAL + 1.))); |
|
|
float value = (signal < (-10 * (NUM_LIGHTS_PER_DIAL - i + 1.) / (NUM_LIGHTS_PER_DIAL + 1.))); |
|
|
setLightRGB(lightId + 3 * i, args, value, 0.65f * value, 0.f); |
|
|
|
|
|
|
|
|
// orange |
|
|
|
|
|
setLightRGBSmooth(lightId + 3 * i, args, value, 0.4f * value, 0.f); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
json_t* dataToJson() override { |
|
|
|
|
|
json_t* rootJ = json_object(); |
|
|
|
|
|
json_object_set_new(rootJ, "break10VNormalForAudioMode", json_boolean(break10VNormalForAudioMode)); |
|
|
|
|
|
return rootJ; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void dataFromJson(json_t* rootJ) override { |
|
|
|
|
|
json_t* break10VNormalAudioJ = json_object_get(rootJ, "break10VNormalForAudioMode"); |
|
|
|
|
|
|
|
|
|
|
|
if (break10VNormalAudioJ) { |
|
|
|
|
|
break10VNormalForAudioMode = json_boolean_value(break10VNormalAudioJ); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct CKSSThreeDragable : app::SvgSlider { |
|
|
|
|
|
CKSSThreeDragable() { |
|
|
|
|
|
math::Vec margin = math::Vec(0, 0); |
|
|
|
|
|
maxHandlePos = math::Vec(1, 1).plus(margin); |
|
|
|
|
|
minHandlePos = math::Vec(1, 18).plus(margin); |
|
|
|
|
|
setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CKSSThree_bg.svg"))); |
|
|
|
|
|
setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CKSSThree_fg.svg"))); |
|
|
|
|
|
background->box.pos = margin; |
|
|
|
|
|
box.size = background->box.size.plus(margin.mult(2)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// disable double click as this messes with click to advance |
|
|
|
|
|
void onDoubleClick(const event::DoubleClick& e) override { } |
|
|
|
|
|
|
|
|
|
|
|
// cycle through the values (with reset) on click only (not drag) |
|
|
|
|
|
void onAction(const ActionEvent& e) override { |
|
|
|
|
|
ParamQuantity* paramQuantity = getParamQuantity(); |
|
|
|
|
|
float range = paramQuantity->maxValue - paramQuantity->minValue; |
|
|
|
|
|
float newValue = paramQuantity->getValue() + 1.f; |
|
|
|
|
|
if (newValue > paramQuantity->maxValue) { |
|
|
|
|
|
newValue -= range + 1.f; |
|
|
|
|
|
} |
|
|
|
|
|
paramQuantity->setValue(newValue); |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -165,11 +308,11 @@ struct MotionMTRWidget : ModuleWidget { |
|
|
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0))); |
|
|
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0))); |
|
|
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); |
|
|
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); |
|
|
|
|
|
|
|
|
addParam(createParam<CKSSThree>(mm2px(Vec(1.298, 17.851)), module, MotionMTR::MODE1_PARAM)); |
|
|
|
|
|
|
|
|
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(1.298, 17.851)), module, MotionMTR::MODE1_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.217, 22.18)), module, MotionMTR::CTRL_1_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.217, 22.18)), module, MotionMTR::CTRL_1_PARAM)); |
|
|
addParam(createParam<CKSSThree>(mm2px(Vec(23.762, 46.679)), module, MotionMTR::MODE2_PARAM)); |
|
|
|
|
|
|
|
|
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(23.762, 46.679)), module, MotionMTR::MODE2_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(11.777, 50.761)), module, MotionMTR::CTRL_2_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(11.777, 50.761)), module, MotionMTR::CTRL_2_PARAM)); |
|
|
addParam(createParam<CKSSThree>(mm2px(Vec(1.34, 74.461)), module, MotionMTR::MODE3_PARAM)); |
|
|
|
|
|
|
|
|
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(1.34, 74.461)), module, MotionMTR::MODE3_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.31, 78.89)), module, MotionMTR::CTRL_3_PARAM)); |
|
|
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.31, 78.89)), module, MotionMTR::CTRL_3_PARAM)); |
|
|
|
|
|
|
|
|
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.008, 100.315)), module, MotionMTR::IN1_INPUT)); |
|
|
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.008, 100.315)), module, MotionMTR::IN1_INPUT)); |
|
|
@@ -202,6 +345,21 @@ struct MotionMTRWidget : ModuleWidget { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void appendContextMenu(Menu* menu) override { |
|
|
|
|
|
MotionMTR* module = dynamic_cast<MotionMTR*>(this->module); |
|
|
|
|
|
assert(module); |
|
|
|
|
|
|
|
|
|
|
|
menu->addChild(new MenuSeparator()); |
|
|
|
|
|
menu->addChild(createSubmenuItem("Hardware compatibility", "", |
|
|
|
|
|
[ = ](Menu * menu) { |
|
|
|
|
|
menu->addChild(createBoolPtrMenuItem("Disable 10V normal in audio mode", "", &module->break10VNormalForAudioMode)); |
|
|
|
|
|
} |
|
|
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|