@@ -408,8 +408,9 @@ struct MidiWidget : LedDisplay { | |||||
//////////////////// | //////////////////// | ||||
struct LightWidget : TransparentWidget { | struct LightWidget : TransparentWidget { | ||||
NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | |||||
NVGcolor color = nvgRGBA(0, 0, 0, 0); | NVGcolor color = nvgRGBA(0, 0, 0, 0); | ||||
NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | |||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
virtual void drawLight(NVGcontext *vg); | virtual void drawLight(NVGcontext *vg); | ||||
virtual void drawHalo(NVGcontext *vg); | virtual void drawHalo(NVGcontext *vg); | ||||
@@ -417,8 +418,6 @@ struct LightWidget : TransparentWidget { | |||||
/** Mixes a list of colors based on a list of brightness values */ | /** Mixes a list of colors based on a list of brightness values */ | ||||
struct MultiLightWidget : LightWidget { | struct MultiLightWidget : LightWidget { | ||||
/** Color of the "off" state */ | |||||
NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | |||||
/** Colors of each value state */ | /** Colors of each value state */ | ||||
std::vector<NVGcolor> baseColors; | std::vector<NVGcolor> baseColors; | ||||
void addBaseColor(NVGcolor baseColor); | void addBaseColor(NVGcolor baseColor); | ||||
@@ -26,11 +26,33 @@ inline NVGcolor colorPlus(NVGcolor a, NVGcolor b) { | |||||
return a; | return a; | ||||
} | } | ||||
inline NVGcolor colorMult(NVGcolor a, NVGcolor b) { | |||||
for (int i = 0; i < 3; i++) | |||||
a.rgba[i] *= b.rgba[i]; | |||||
return a; | |||||
} | |||||
inline NVGcolor colorMult(NVGcolor a, float x) { | inline NVGcolor colorMult(NVGcolor a, float x) { | ||||
for (int i = 0; i < 3; i++) | for (int i = 0; i < 3; i++) | ||||
a.rgba[i] *= x; | a.rgba[i] *= x; | ||||
return a; | return a; | ||||
} | } | ||||
/** Screen blending with alpha compositing */ | |||||
inline NVGcolor colorScreen(NVGcolor a, NVGcolor b) { | |||||
if (a.a == 0.0) | |||||
return b; | |||||
if (b.a == 0.0) | |||||
return a; | |||||
a = colorMult(a, a.a); | |||||
b = colorMult(b, b.a); | |||||
NVGcolor c = colorMinus(colorPlus(a, b), colorMult(a, b)); | |||||
c.a = a.a + b.a - a.a * b.a; | |||||
c = colorMult(c, 1.f / c.a); | |||||
c = colorClip(c); | |||||
return c; | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -16,7 +16,11 @@ void LightWidget::drawLight(NVGcontext *vg) { | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgCircle(vg, radius, radius, radius); | nvgCircle(vg, radius, radius, radius); | ||||
// Solid color | |||||
// Background | |||||
nvgFillColor(vg, bgColor); | |||||
nvgFill(vg); | |||||
// Foreground | |||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
@@ -28,13 +32,13 @@ void LightWidget::drawLight(NVGcontext *vg) { | |||||
void LightWidget::drawHalo(NVGcontext *vg) { | void LightWidget::drawHalo(NVGcontext *vg) { | ||||
float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
float oradius = radius + 15.0; | |||||
float oradius = radius + 20.0; | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | ||||
NVGpaint paint; | NVGpaint paint; | ||||
NVGcolor icol = colorMult(color, 0.25); | |||||
NVGcolor icol = colorMult(color, 0.10); | |||||
NVGcolor ocol = nvgRGB(0, 0, 0); | NVGcolor ocol = nvgRGB(0, 0, 0); | ||||
paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | ||||
nvgFillPaint(vg, paint); | nvgFillPaint(vg, paint); | ||||
@@ -11,11 +11,11 @@ void MultiLightWidget::addBaseColor(NVGcolor baseColor) { | |||||
void MultiLightWidget::setValues(const std::vector<float> &values) { | void MultiLightWidget::setValues(const std::vector<float> &values) { | ||||
assert(values.size() == baseColors.size()); | assert(values.size() == baseColors.size()); | ||||
color = nvgRGBf(0, 0, 0); | |||||
color = nvgRGBAf(0, 0, 0, 0); | |||||
for (size_t i = 0; i < baseColors.size(); i++) { | for (size_t i = 0; i < baseColors.size(); i++) { | ||||
NVGcolor c = baseColors[i]; | NVGcolor c = baseColors[i]; | ||||
c = colorMult(c, values[i]); | |||||
color = colorPlus(color, c); | |||||
c.a *= clamp(values[i], 0.f, 1.f); | |||||
color = colorScreen(color, c); | |||||
} | } | ||||
color = colorClip(color); | color = colorClip(color); | ||||
} | } | ||||