| @@ -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); | ||||
| } | } | ||||