@@ -7,13 +7,13 @@ | |||
namespace rack { | |||
struct Model; | |||
struct Module; | |||
struct Wire; | |||
struct RackWidget; | |||
struct ParamWidget; | |||
struct Port; | |||
struct Scene; | |||
//////////////////// | |||
// module | |||
@@ -23,7 +23,6 @@ struct Scene; | |||
#define RACK_GRID_WIDTH 15 | |||
#define RACK_GRID_HEIGHT 380 | |||
struct Model; | |||
struct ModuleWidget : OpaqueWidget { | |||
Model *model = NULL; | |||
/** Owns the module pointer */ | |||
@@ -168,12 +167,6 @@ struct CircularShadow : TransparentWidget { | |||
void draw(NVGcontext *vg) override; | |||
}; | |||
struct LightWidget : TransparentWidget { | |||
NVGcolor bgColor = nvgRGBf(0, 0, 0); | |||
NVGcolor color = nvgRGBf(1, 1, 1); | |||
void draw(NVGcontext *vg) override; | |||
}; | |||
struct ParamWidget : OpaqueWidget, QuantityWidget { | |||
Module *module = NULL; | |||
int paramId; | |||
@@ -309,6 +302,29 @@ struct SVGScrew : FramebufferWidget { | |||
SVGScrew(); | |||
}; | |||
//////////////////// | |||
// lights | |||
//////////////////// | |||
struct LightWidget : TransparentWidget { | |||
NVGcolor bgColor = nvgRGBf(0, 0, 0); | |||
NVGcolor color = nvgRGBf(1, 1, 1); | |||
void draw(NVGcontext *vg) override; | |||
}; | |||
/** A LightWidget that points to a module's Light or a range of lights */ | |||
struct ModuleLightWidget : LightWidget { | |||
Module *module = NULL; | |||
int lightId; | |||
}; | |||
/** Mixes colors based on the brightness of the module light at lightId, lightId + 1, etc */ | |||
struct ColorLightWidget : ModuleLightWidget { | |||
std::vector<NVGcolor> colors; | |||
void addColor(NVGcolor c); | |||
void step() override; | |||
}; | |||
//////////////////// | |||
// scene | |||
//////////////////// | |||
@@ -337,7 +337,6 @@ struct Rogan1PWhite : Rogan1P { | |||
struct SynthTechAlco : SVGKnob { | |||
SynthTechAlco() { | |||
box.size = Vec(45, 45); | |||
minAngle = -0.82*M_PI; | |||
maxAngle = 0.82*M_PI; | |||
setSVG(SVG::load(assetGlobal("res/ComponentLibrary/SynthTechAlco.svg"))); | |||
@@ -423,95 +422,55 @@ struct CL1362Port : SVGPort { | |||
// Lights | |||
//////////////////// | |||
struct ValueLight : LightWidget { | |||
float *value = NULL; | |||
virtual void setValue(float v) {} | |||
void step() override { | |||
if (value) | |||
setValue(*value); | |||
struct RedLight : ColorLightWidget { | |||
RedLight() { | |||
addColor(COLOR_RED); | |||
} | |||
}; | |||
struct ColorValueLight : ValueLight { | |||
NVGcolor baseColor; | |||
void setValue(float v) override { | |||
v = sqrtBipolar(v); | |||
color = baseColor; | |||
color.a *= clampf(v, 0.0, 1.0); | |||
struct GreenLight : ColorLightWidget { | |||
GreenLight() { | |||
addColor(COLOR_GREEN); | |||
} | |||
}; | |||
struct RedValueLight : ColorValueLight { | |||
RedValueLight() { | |||
baseColor = COLOR_RED; | |||
struct GreenRedLight : ColorLightWidget { | |||
GreenRedLight() { | |||
addColor(COLOR_GREEN); | |||
addColor(COLOR_RED); | |||
} | |||
}; | |||
struct YellowValueLight : ColorValueLight { | |||
YellowValueLight() { | |||
baseColor = COLOR_YELLOW; | |||
} | |||
}; | |||
struct GreenValueLight : ColorValueLight { | |||
GreenValueLight() { | |||
baseColor = COLOR_GREEN; | |||
} | |||
}; | |||
struct PolarityLight : ValueLight { | |||
NVGcolor posColor; | |||
NVGcolor negColor; | |||
void setValue(float v) override { | |||
v = sqrtBipolar(v); | |||
color = (v >= 0.0) ? posColor : negColor; | |||
color.a *= clampf(fabsf(v), 0.0, 1.0); | |||
} | |||
}; | |||
struct GreenRedPolarityLight : PolarityLight { | |||
GreenRedPolarityLight() { | |||
posColor = COLOR_GREEN; | |||
negColor = COLOR_RED; | |||
} | |||
}; | |||
struct ModeValueLight : ValueLight { | |||
std::vector<NVGcolor> colors; | |||
void setValue(float v) override { | |||
int mode = clampi((int)roundf(v), 0, colors.size()); | |||
color = colors[mode]; | |||
} | |||
void addColor(NVGcolor color) { | |||
colors.push_back(color); | |||
} | |||
}; | |||
/** 5mm diameter */ | |||
template <typename BASE> | |||
struct LargeLight : BASE { | |||
LargeLight() { | |||
this->box.size = Vec(20, 20); | |||
this->box.size = Vec(15, 15); | |||
} | |||
}; | |||
/** 3mm diameter */ | |||
template <typename BASE> | |||
struct MediumLight : BASE { | |||
MediumLight() { | |||
this->box.size = Vec(12, 12); | |||
this->box.size = Vec(9, 9); | |||
} | |||
}; | |||
/** 2mm diameter */ | |||
template <typename BASE> | |||
struct SmallLight : BASE { | |||
SmallLight() { | |||
this->box.size = Vec(8, 8); | |||
this->box.size = Vec(6, 6); | |||
} | |||
}; | |||
/** 1mm diameter */ | |||
template <typename BASE> | |||
struct TinyLight : BASE { | |||
TinyLight() { | |||
this->box.size = Vec(5, 5); | |||
this->box.size = Vec(3, 3); | |||
} | |||
}; | |||
@@ -32,6 +32,10 @@ struct Output { | |||
struct Light { | |||
/** The square of the brightness value */ | |||
float value = 0.0; | |||
float getBrightness(); | |||
void setBrightness(float brightness) { | |||
value = brightness * brightness; | |||
} | |||
void setBrightnessSmooth(float brightness); | |||
}; | |||
@@ -2,12 +2,12 @@ | |||
#include "util.hpp" | |||
#include "math.hpp" | |||
#include "asset.hpp" | |||
#include "plugin.hpp" | |||
#include "engine.hpp" | |||
#include "gui.hpp" | |||
#include "app.hpp" | |||
#include "components.hpp" | |||
#include "asset.hpp" | |||
namespace rack { | |||
@@ -34,9 +34,16 @@ Model *createModel(std::string manufacturerSlug, std::string manufacturerName, s | |||
return model; | |||
} | |||
template <class TParam> | |||
template <class TScrew> | |||
Widget *createScrew(Vec pos) { | |||
Widget *screw = new TScrew(); | |||
screw->box.pos = pos; | |||
return screw; | |||
} | |||
template <class TParamWidget> | |||
ParamWidget *createParam(Vec pos, Module *module, int paramId, float minValue, float maxValue, float defaultValue) { | |||
ParamWidget *param = new TParam(); | |||
ParamWidget *param = new TParamWidget(); | |||
param->box.pos = pos; | |||
param->module = module; | |||
param->paramId = paramId; | |||
@@ -65,18 +72,12 @@ Port *createOutput(Vec pos, Module *module, int outputId) { | |||
return port; | |||
} | |||
template <class TScrew> | |||
Widget *createScrew(Vec pos) { | |||
Widget *screw = new TScrew(); | |||
screw->box.pos = pos; | |||
return screw; | |||
} | |||
template <class TLight> | |||
ValueLight *createValueLight(Vec pos, float *value) { | |||
ValueLight *light = new TLight(); | |||
template<class TModuleLightWidget> | |||
ModuleLightWidget *createLight(Vec pos, Module *module, int lightId) { | |||
ModuleLightWidget *light = new TModuleLightWidget(); | |||
light->box.pos = pos; | |||
light->value = value; | |||
light->module = module; | |||
light->lightId = lightId; | |||
return light; | |||
} | |||
@@ -0,0 +1,24 @@ | |||
#include "app.hpp" | |||
#include "engine.hpp" | |||
namespace rack { | |||
void ColorLightWidget::addColor(NVGcolor c) { | |||
colors.push_back(c); | |||
} | |||
void ColorLightWidget::step() { | |||
color = nvgRGBf(0, 0, 0); | |||
for (int i = 0; i < (int)colors.size(); i++) { | |||
NVGcolor c = colors[i]; | |||
float brightness = module->lights[lightId + i].getBrightness(); | |||
color.r += c.r * brightness; | |||
color.g += c.g * brightness; | |||
color.b += c.b * brightness; | |||
} | |||
} | |||
} // namespace rack |
@@ -87,10 +87,10 @@ WireWidget::WireWidget() { | |||
lastWireColorId = (lastWireColorId + 1) % LENGTHOF(wireColors); | |||
color = wireColors[lastWireColorId]; | |||
inputLight = construct<PolarityLight>(&PolarityLight::posColor, COLOR_GREEN, &PolarityLight::negColor, COLOR_RED); | |||
outputLight = construct<PolarityLight>(&PolarityLight::posColor, COLOR_GREEN, &PolarityLight::negColor, COLOR_RED); | |||
addChild(inputLight); | |||
addChild(outputLight); | |||
// inputLight = construct<PolarityLight>(&PolarityLight::posColor, COLOR_GREEN, &PolarityLight::negColor, COLOR_RED); | |||
// outputLight = construct<PolarityLight>(&PolarityLight::posColor, COLOR_GREEN, &PolarityLight::negColor, COLOR_RED); | |||
// addChild(inputLight); | |||
// addChild(outputLight); | |||
} | |||
WireWidget::~WireWidget() { | |||
@@ -166,6 +166,7 @@ void WireWidget::drawPlugs(NVGcontext *vg) { | |||
drawPlug(vg, inputPos, color); | |||
// Draw plug light | |||
/* | |||
if (gToolbar->plugLightButton->value > 0.0) { | |||
if (wire) { | |||
Output &output = wire->outputModule->outputs[wire->outputId]; | |||
@@ -188,6 +189,7 @@ void WireWidget::drawPlugs(NVGcontext *vg) { | |||
outputLight->visible = false; | |||
inputLight->visible = false; | |||
} | |||
*/ | |||
Widget::draw(vg); | |||
} | |||
@@ -18,6 +18,9 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
enum OutputIds { | |||
NUM_OUTPUTS = 16 | |||
}; | |||
enum LightIds { | |||
NUM_LIGHTS = 16 | |||
}; | |||
int cc[NUM_OUTPUTS]; | |||
int ccNum[NUM_OUTPUTS]; | |||
@@ -25,10 +28,9 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
bool ccSyncFirst[NUM_OUTPUTS]; | |||
bool ccNumInited[NUM_OUTPUTS]; | |||
bool onFocus[NUM_OUTPUTS]; | |||
float lights[NUM_OUTPUTS]; | |||
MIDICCToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||
MIDICCToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
cc[i] = 0; | |||
ccNum[i] = i; | |||
@@ -97,7 +99,7 @@ void MIDICCToCVInterface::step() { | |||
for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
lights[i] = ccSync[i] / 127.0; | |||
lights[i].setBrightness(ccSync[i] / 127.0); | |||
outputs[i].value = cc[i] / 127.0 * 10.0; | |||
} | |||
@@ -294,8 +296,7 @@ MIDICCToCVWidget::MIDICCToCVWidget() { | |||
yPos += labelHeight + margin; | |||
addOutput(createOutput<PJ3410Port>(Vec((i % 4) * (63) + 10, yPos + 5), module, i)); | |||
addChild(createValueLight<SmallLight<RedValueLight>>(Vec((i % 4) * (63) + 32, yPos + 5), | |||
&module->lights[i])); | |||
addChild(createLight<SmallLight<RedLight>>(Vec((i % 4) * (63) + 32, yPos + 5), module, i)); | |||
if ((i + 1) % 4 == 0) { | |||
yPos += 47 + margin; | |||
@@ -26,6 +26,10 @@ struct MIDIToCVInterface : MidiIO, Module { | |||
CHANNEL_AFTERTOUCH_OUTPUT, | |||
NUM_OUTPUTS | |||
}; | |||
enum LightIds { | |||
RESET_LIGHT, | |||
NUM_LIGHTS | |||
}; | |||
std::list<int> notes; | |||
bool pedal = false; | |||
@@ -38,9 +42,8 @@ struct MIDIToCVInterface : MidiIO, Module { | |||
bool retriggered = false; | |||
SchmittTrigger resetTrigger; | |||
float resetLight = 0.0; | |||
MIDIToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||
MIDIToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
} | |||
@@ -78,14 +81,11 @@ void MIDIToCVInterface::resetMidi() { | |||
pitchWheel = 64; | |||
afterTouch = 0; | |||
vel = 0; | |||
resetLight = 1.0; | |||
outputs[GATE_OUTPUT].value = 0.0; | |||
notes.clear(); | |||
} | |||
void MIDIToCVInterface::step() { | |||
float sampleRate = engineGetSampleRate(); | |||
if (isPortOpen()) { | |||
std::vector<unsigned char> message; | |||
@@ -109,10 +109,7 @@ void MIDIToCVInterface::step() { | |||
return; | |||
} | |||
if (resetLight > 0) { | |||
resetLight -= resetLight / 0.55 / sampleRate; // fade out light | |||
} | |||
lights[RESET_LIGHT].value -= lights[RESET_LIGHT].value / 0.55 / engineGetSampleRate(); // fade out light | |||
outputs[GATE_OUTPUT].value = gate ? 10.0 : 0.0; | |||
outputs[MOD_OUTPUT].value = mod / 127.0 * 10.0; | |||
@@ -228,7 +225,7 @@ MidiToCVWidget::MidiToCVWidget() { | |||
} | |||
addParam(createParam<LEDButton>(Vec(7 * 15, labelHeight), module, MIDIToCVInterface::RESET_PARAM, 0.0, 1.0, 0.0)); | |||
addChild(createValueLight<SmallLight<RedValueLight>>(Vec(7 * 15 + 5, labelHeight + 5), &module->resetLight)); | |||
addChild(createLight<SmallLight<RedLight>>(Vec(7 * 15 + 5, labelHeight + 5), module, MIDIToCVInterface::RESET_LIGHT)); | |||
{ | |||
Label *label = new Label(); | |||
label->box.pos = Vec(margin, yPos); | |||
@@ -260,7 +257,7 @@ MidiToCVWidget::MidiToCVWidget() { | |||
} | |||
std::string labels[MIDIToCVInterface::NUM_OUTPUTS] = {"1V/oct", "Gate", "Velocity", "Mod Wheel", "Pitch Wheel", | |||
"Aftertouch"}; | |||
"Aftertouch"}; | |||
for (int i = 0; i < MIDIToCVInterface::NUM_OUTPUTS; i++) { | |||
Label *label = new Label(); | |||
@@ -27,6 +27,10 @@ struct QuadMIDIToCVInterface : MidiIO, Module { | |||
AT_OUTPUT = 12, | |||
NUM_OUTPUTS = 16 | |||
}; | |||
enum LightIds { | |||
RESET_LIGHT, | |||
NUM_LIGHTS | |||
}; | |||
enum Modes { | |||
ROTATE, | |||
@@ -46,9 +50,8 @@ struct QuadMIDIToCVInterface : MidiIO, Module { | |||
std::list<int> open; | |||
SchmittTrigger resetTrigger; | |||
float resetLight = 0.0; | |||
QuadMIDIToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||
QuadMIDIToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
} | |||
@@ -89,13 +92,10 @@ void QuadMIDIToCVInterface::resetMidi() { | |||
open.clear(); | |||
pedal = false; | |||
resetLight = 1.0; | |||
lights[RESET_LIGHT].value = 1.0; | |||
} | |||
void QuadMIDIToCVInterface::step() { | |||
float sampleRate = engineGetSampleRate(); | |||
if (isPortOpen()) { | |||
std::vector<unsigned char> message; | |||
int msgsProcessed = 0; | |||
@@ -124,10 +124,7 @@ void QuadMIDIToCVInterface::step() { | |||
return; | |||
} | |||
if (resetLight > 0) { | |||
resetLight -= resetLight / 0.55 / sampleRate; // fade out light | |||
} | |||
lights[RESET_LIGHT].value -= lights[RESET_LIGHT].value / 0.55 / engineGetSampleRate(); // fade out light | |||
} | |||
@@ -304,7 +301,7 @@ QuadMidiToCVWidget::QuadMidiToCVWidget() { | |||
addParam(createParam<LEDButton>(Vec(12 * 15, labelHeight), module, QuadMIDIToCVInterface::RESET_PARAM, 0.0, 1.0, | |||
0.0)); | |||
addChild(createValueLight<SmallLight<RedValueLight>>(Vec(12 * 15 + 5, labelHeight + 5), &module->resetLight)); | |||
addChild(createLight<SmallLight<RedLight>>(Vec(12 * 15 + 5, labelHeight + 5), module, QuadMIDIToCVInterface::RESET_LIGHT)); | |||
{ | |||
Label *label = new Label(); | |||
label->box.pos = Vec(margin, yPos); | |||
@@ -33,8 +33,12 @@ static int smoothParamId; | |||
static float smoothValue; | |||
float Light::getBrightness() { | |||
return sqrtf(value); | |||
} | |||
void Light::setBrightnessSmooth(float brightness) { | |||
value += (powf(brightness, 2) - value) / sampleRate * 60.0; | |||
value += (brightness * brightness - value) / sampleRate * 60.0; | |||
} | |||