commit 8934b2dc7c0e9b0ad692f4823391ec943904bec1
parent 3156cbf6756d8b429b90af2641dec9b17ef070f2
Author: Matt Demanett <matt@demanett.net>
Date: Wed, 20 Oct 2021 00:07:04 -0400
Rack2: nightmode, take 2.
Diffstat:
15 files changed, 343 insertions(+), 190 deletions(-)
diff --git a/src/Blank3.cpp b/src/Blank3.cpp
@@ -17,47 +17,51 @@ void Blank3::processAll(const ProcessArgs& args) {
}
}
-struct Blank3Display : OpaqueWidget {
+struct Blank3Display : DisplayWidget {
Blank3* _module;
const char* _text;
std::string _fontPath;
Blank3Display(Blank3* module, const char* text)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _text(text)
, _fontPath(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf"))
{
}
- void draw(const DrawArgs& args) override {
- std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
-
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
const Skins& skins = Skins::skins();
std::string skin = skins.defaultKey();
bool haveLevel = false;
float level = 0.0f;
- if (_module && !_module->isBypassed()) {
+ if (lit) {
haveLevel = _module->_level;
level = _module->_level;
skin = _module->_skin;
}
NVGcolor textColor = nvgRGBA(0x33, 0x33, 0x33, 0xff);
- // NVGcolor bgTextColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
NVGcolor bgColor = nvgRGBA(0xdd, 0xdd, 0xdd, 0xff);
const char* pathStroke = skins.skinCssValue(skin, "path-stroke");
if (pathStroke) {
textColor = Skins::cssColorToNVGColor(pathStroke, textColor);
}
- const char* backgroundFill = skins.skinCssValue(skin, "background-fill");
- if (backgroundFill) {
- bgColor = Skins::cssColorToNVGColor(backgroundFill, bgColor);
- }
NVGcolor bgTextColor = nvgRGBAf(0.5f * (textColor.r + bgColor.r), 0.5f * (textColor.g + bgColor.g), 0.5f * (textColor.b + bgColor.b), 1.0f);
+ const int split = 65;
+ drawText(args, 0, 0, box.size.x, split - 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split, box.size.x, box.size.y, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split - 10, box.size.x / 2 - 5, 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, box.size.x / 2 + 5, split - 10, box.size.x, 10, haveLevel, level, textColor, bgTextColor);
+ }
+ void drawText(const DrawArgs& args, int sx, int sy, int sw, int sh, bool haveLevel, float level, const NVGcolor& textColor, const NVGcolor& bgTextColor) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
float offsetX = box.size.x / 2.0f;
float offsetY = box.size.y / 2.0f;
nvgSave(args.vg);
+ nvgScissor(args.vg, 0, 0, box.size.x, box.size.y);
+ nvgIntersectScissor(args.vg, sx, sy, sw, sh);
nvgTranslate(args.vg, offsetX, offsetY);
nvgRotate(args.vg, M_PI/2.0f);
nvgTranslate(args.vg, -offsetY, offsetX);
@@ -69,7 +73,6 @@ struct Blank3Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
else {
- nvgGlobalTint(args.vg, color::WHITE);
nvgFillColor(args.vg, bgTextColor);
nvgText(args.vg, 0, 0, _text, NULL);
if (level > 0.0001f) {
@@ -77,10 +80,6 @@ struct Blank3Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 55, -20, 10, 10);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
nvgRestore(args.vg);
}
};
diff --git a/src/Blank3.hpp b/src/Blank3.hpp
@@ -30,7 +30,7 @@ struct Blank3 : BGModule {
Blank3() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configInput(IN_INPUT, "Signal");
+ configInput(IN_INPUT, "Easter egg");
sampleRateChange();
}
diff --git a/src/Blank6.cpp b/src/Blank6.cpp
@@ -17,47 +17,52 @@ void Blank6::processAll(const ProcessArgs& args) {
}
}
-struct Blank6Display : OpaqueWidget {
+struct Blank6Display : DisplayWidget {
Blank6* _module;
const char* _text;
std::string _fontPath;
Blank6Display(Blank6* module, const char* text)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _text(text)
, _fontPath(asset::plugin(pluginInstance, "res/fonts/audiowide.ttf"))
{
}
- void draw(const DrawArgs& args) override {
- std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
-
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
const Skins& skins = Skins::skins();
std::string skin = skins.defaultKey();
bool haveLevel = false;
float level = 0.0f;
- if (_module && !_module->isBypassed()) {
+ if (lit) {
haveLevel = _module->_level;
level = _module->_level;
skin = _module->_skin;
}
NVGcolor textColor = nvgRGBA(0x33, 0x33, 0x33, 0xff);
- // NVGcolor bgTextColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
NVGcolor bgColor = nvgRGBA(0xdd, 0xdd, 0xdd, 0xff);
const char* pathStroke = skins.skinCssValue(skin, "path-stroke");
if (pathStroke) {
textColor = Skins::cssColorToNVGColor(pathStroke, textColor);
}
- const char* backgroundFill = skins.skinCssValue(skin, "background-fill");
- if (backgroundFill) {
- bgColor = Skins::cssColorToNVGColor(backgroundFill, bgColor);
- }
NVGcolor bgTextColor = nvgRGBAf(0.5f * (textColor.r + bgColor.r), 0.5f * (textColor.g + bgColor.g), 0.5f * (textColor.b + bgColor.b), 1.0f);
+ const int split = 107;
+ drawText(args, 0, 0, box.size.x, split - 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split, box.size.x, box.size.y, haveLevel, level, textColor, bgTextColor);
+ drawText(args, 0, split - 10, box.size.x / 2 - 5, 10, haveLevel, level, textColor, bgTextColor);
+ drawText(args, box.size.x / 2 + 5, split - 10, box.size.x, 10, haveLevel, level, textColor, bgTextColor);
+ }
+
+ void drawText(const DrawArgs& args, int sx, int sy, int sw, int sh, bool haveLevel, float level, const NVGcolor& textColor, const NVGcolor& bgTextColor) {
+ std::shared_ptr<Font> font = APP->window->loadFont(_fontPath);
float offsetX = box.size.x / 2.0f;
float offsetY = box.size.y / 2.0f;
nvgSave(args.vg);
+ nvgScissor(args.vg, 0, 0, box.size.x, box.size.y);
+ nvgIntersectScissor(args.vg, sx, sy, sw, sh);
nvgTranslate(args.vg, offsetX, offsetY);
nvgRotate(args.vg, M_PI/2.0f);
nvgTranslate(args.vg, -offsetY, offsetX);
@@ -69,7 +74,6 @@ struct Blank6Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
else {
- nvgGlobalTint(args.vg, color::WHITE);
nvgFillColor(args.vg, bgTextColor);
nvgText(args.vg, 0, 0, _text, NULL);
if (level > 0.0001f) {
@@ -77,10 +81,6 @@ struct Blank6Display : OpaqueWidget {
nvgText(args.vg, 0, 0, _text, NULL);
}
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 97, -20, 10, 10);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
nvgRestore(args.vg);
}
};
diff --git a/src/Blank6.hpp b/src/Blank6.hpp
@@ -30,7 +30,7 @@ struct Blank6 : BGModule {
Blank6() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
- configInput(IN_INPUT, "Signal");
+ configInput(IN_INPUT, "Easter egg");
sampleRateChange();
}
diff --git a/src/Mono.cpp b/src/Mono.cpp
@@ -55,7 +55,7 @@ void Mono::processAll(const ProcessArgs& args) {
}
struct MonoWidget : BGModuleWidget {
- struct ChannelsDisplay : OpaqueWidget {
+ struct ChannelsDisplay : LightEmittingWidget<OpaqueWidget> {
const NVGcolor inactiveBgColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
const NVGcolor activeBgColor = nvgRGBA(0x66, 0x66, 0x66, 0xff);
Mono* _module;
@@ -63,35 +63,42 @@ struct MonoWidget : BGModuleWidget {
ChannelsDisplay(Mono* module) : _module(module) {
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
nvgSave(args.vg);
for (int i = 0; i < _module->maxChannels; ++i) {
nvgBeginPath(args.vg);
- if (!_module || _module->isBypassed() || i >= _module->_activeChannels) {
+ if (i >= _module->_activeChannels) {
+ nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
nvgFillColor(args.vg, inactiveBgColor);
+ nvgFill(args.vg);
}
- else {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
- nvgFillColor(args.vg, activeBgColor);
- nvgRestore(args.vg);
- }
- nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
- nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
- if (_module && !_module->isBypassed() && _module->_channelLevels[i] > 0.0f) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(_module->_channelLevels[i])));
+ void drawLit(const DrawArgs& args) override {
+ nvgSave(args.vg);
+ for (int i = 0; i < _module->maxChannels; ++i) {
+ nvgBeginPath(args.vg);
+ if (i < _module->_activeChannels) {
+ nvgCircle(args.vg, (i % 4) * 10 + 5.0f, (i / 4) * 10 + 5.0f, 3.2f);
+ nvgFillColor(args.vg, activeBgColor);
nvgFill(args.vg);
- nvgRestore(args.vg);
+ if (_module->_channelLevels[i] > 0.0f) {
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(_module->_channelLevels[i])));
+ nvgFill(args.vg);
+ }
}
}
nvgRestore(args.vg);
}
};
- struct CompressionDisplay : OpaqueWidget {
+ struct CompressionDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -111,7 +118,21 @@ struct MonoWidget : BGModuleWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
+ nvgSave(args.vg);
+ for (int i = 0; i < 35; i += 5) {
+ drawBox(args, i);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
float compressionDb = 0.0f;
if (_module && !_module->isBypassed()) {
compressionDb = _module->_compressionDb;
@@ -120,21 +141,19 @@ struct MonoWidget : BGModuleWidget {
nvgSave(args.vg);
for (int i = 0; i < 35; i += 5) {
const Level& l = _levels.at(i / 5);
-
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (compressionDb > l.db) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
- nvgRestore(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, 3, offset + 1, 5, 4);
+ }
};
static constexpr int hp = 3;
diff --git a/src/Pressor.cpp b/src/Pressor.cpp
@@ -192,7 +192,7 @@ void Pressor::processChannel(const ProcessArgs& args, int c) {
}
struct PressorWidget : BGModuleWidget {
- struct CompressionDisplay : OpaqueWidget {
+ struct CompressionDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -212,7 +212,21 @@ struct PressorWidget : BGModuleWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
+ nvgSave(args.vg);
+ for (int i = 0; i < 80; i += 5) {
+ drawBox(args, i);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
float compressionDb = 0.0f;
if (_module && !_module->isBypassed()) {
compressionDb = _module->_compressionDb;
@@ -221,21 +235,19 @@ struct PressorWidget : BGModuleWidget {
nvgSave(args.vg);
for (int i = 0; i < 80; i += 5) {
const Level& l = _levels.at(i / 5);
-
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (compressionDb > l.db) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
- nvgRestore(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, 3, offset + 1, 5, 4);
+ }
};
static constexpr int hp = 15;
diff --git a/src/Reftone.cpp b/src/Reftone.cpp
@@ -34,7 +34,7 @@ void Reftone::processAll(const ProcessArgs& args) {
}
}
-struct ReftoneDisplay : TransparentWidget {
+struct ReftoneDisplay : DisplayWidget {
const NVGcolor _textColor = nvgRGBA(0x00, 0xff, 0x00, 0xee);
Reftone* _module;
@@ -45,13 +45,16 @@ struct ReftoneDisplay : TransparentWidget {
Reftone* module,
Vec size
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
, _fontPath(asset::plugin(pluginInstance, "res/fonts/inconsolata-bold.ttf"))
{
}
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override;
void drawBackground(const DrawArgs& args);
void drawText(const DrawArgs& args, const char* s, float x, float y, int size);
void drawCenteredText(const DrawArgs& args, const char* s, float y, int size);
@@ -59,11 +62,23 @@ struct ReftoneDisplay : TransparentWidget {
};
void ReftoneDisplay::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ drawOnce(args, isScreenshot(), false);
+ }
+}
+
+void ReftoneDisplay::drawLit(const DrawArgs& args) {
+ if (isLit()) {
+ drawOnce(args, false, true);
+ }
+}
+
+void ReftoneDisplay::drawOnce(const DrawArgs& args, bool screenshot, bool lit) {
int mPitch = 9;
int mOctave = 4;
float mFine = 0.0f;
float mFrequency = 440.0f;
- if (_module) {
+ if (!screenshot) {
mPitch = _module->_pitch;
mOctave = _module->_octave;
mFine = _module->_fine;
@@ -132,11 +147,10 @@ void ReftoneDisplay::draw(const DrawArgs& args) {
}
nvgSave(args.vg);
- if (_module && _module->isBypassed()) {
+ if (!screenshot && !lit) {
drawBackground(args);
}
else {
- nvgGlobalTint(args.vg, color::WHITE);
drawBackground(args);
if (sharpFlat) {
drawText(args, pitch, 3, 20, 28);
diff --git a/src/VU.cpp b/src/VU.cpp
@@ -58,7 +58,7 @@ void VU::processAll(const ProcessArgs& args) {
_rPeakLevel = rPeak;
}
-struct VUDisplay : OpaqueWidget {
+struct VUDisplay : LightEmittingWidget<OpaqueWidget> {
struct Level {
float db;
NVGcolor color;
@@ -76,62 +76,64 @@ struct VUDisplay : OpaqueWidget {
}
}
+ bool isLit() override {
+ return _module && !_module->isBypassed();
+ }
+
void draw(const DrawArgs& args) override {
- float lDb = -100.0f;
- float rDb = -100.0f;
- float lPeakDb = -100.0f;
- float rPeakDb = -100.0f;
- if (_module && !_module->isBypassed()) {
- lDb = amplitudeToDecibels(_module->_lLevel);
- rDb = amplitudeToDecibels(_module->_rLevel);
- lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
- rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
+ nvgSave(args.vg);
+ for (int i = 0; i < 180; i += 5) {
+ drawBox(args, i, true);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
+
+ drawBox(args, i, false);
+ nvgFillColor(args.vg, bgColor);
+ nvgFill(args.vg);
}
+ nvgRestore(args.vg);
+ }
+
+ void drawLit(const DrawArgs& args) override {
+ assert(_module);
+ float lDb = amplitudeToDecibels(_module->_lLevel);
+ float rDb = amplitudeToDecibels(_module->_rLevel);
+ float lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
+ float rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
nvgSave(args.vg);
for (int i = 0; i < 180; i += 5) {
const Level& l = _levels.at(i / 5);
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 3, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (lPeakDb > l.db && lPeakDb < l.db + 2.0f) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i, true);
nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
nvgFill(args.vg);
- nvgRestore(args.vg);
}
if (lDb > l.db) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i, true);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
- nvgRestore(args.vg);
}
- nvgBeginPath(args.vg);
- nvgRect(args.vg, 10, i + 1, 5, 4);
- nvgFillColor(args.vg, bgColor);
- nvgFill(args.vg);
if (rPeakDb > l.db && rPeakDb < l.db + 2.0f) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i, false);
nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
nvgFill(args.vg);
- nvgRestore(args.vg);
}
if (rDb > l.db) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
+ drawBox(args, i, false);
nvgFillColor(args.vg, l.color);
nvgFill(args.vg);
- nvgRestore(args.vg);
}
}
nvgRestore(args.vg);
}
+
+ void drawBox(const DrawArgs& args, int offset, bool left) {
+ nvgBeginPath(args.vg);
+ nvgRect(args.vg, left ? 3 : 10, offset + 1, 5, 4);
+ }
};
struct VUWidget : BGModuleWidget {
diff --git a/src/Walk2.cpp b/src/Walk2.cpp
@@ -169,7 +169,7 @@ void Walk2::processAll(const ProcessArgs& args) {
_historyStep %= _historySteps;
}
-struct Walk2Display : TransparentWidget {
+struct Walk2Display : DisplayWidget {
const int _insetAround = 4;
const NVGcolor _axisColor = nvgRGBA(0xff, 0xff, 0xff, 0x70);
@@ -186,7 +186,8 @@ struct Walk2Display : TransparentWidget {
Walk2* module,
Vec size
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
, _drawSize(2 * (_size.x - 2 * _insetAround), 2 * (_size.y - 2 * _insetAround))
, _midX(_insetAround + _drawSize.x/2)
@@ -225,13 +226,10 @@ struct Walk2Display : TransparentWidget {
}
}
- void draw(const DrawArgs& args) override {
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override {
float strokeWidth = std::max(1.0f, 3.0f - getZoom());
nvgSave(args.vg);
- if (_module && !_module->isBypassed()) {
- nvgGlobalTint(args.vg, color::WHITE);
- }
drawBackground(args);
nvgScissor(args.vg, _insetAround, _insetAround, _drawSize.x / 2, _drawSize.y / 2);
if (_module && _module->_zoomOut) {
@@ -249,7 +247,7 @@ struct Walk2Display : TransparentWidget {
}
drawAxes(args, strokeWidth);
- if (_module && !_module->isBypassed()) {
+ if (lit) {
switch (_module->_traceColor) {
case Walk2::ORANGE_TRACE_COLOR: {
_traceColor = nvgRGBA(0xff, 0x80, 0x00, 0xee);
diff --git a/src/analyzer_base.cpp b/src/analyzer_base.cpp
@@ -453,8 +453,9 @@ void AnalyzerDisplay::channelLabel(int channel, std::string label) {
_channelLabels[channel] = label;
}
-void AnalyzerDisplay::draw(const DrawArgs& args) {
- if (_module) {
+void AnalyzerDisplay::drawOnce(const DrawArgs& args, bool screenshot, bool lit) {
+ if (!screenshot) {
+ assert(_module);
_module->_core._channelsMutex.lock();
}
@@ -462,7 +463,7 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
AmplitudePlot amplitudePlot = DECIBELS_80_AP;
float rangeMinHz = 0.0f;
float rangeMaxHz = 0.0f;
- if (_module) {
+ if (!screenshot) {
frequencyPlot = _module->_frequencyPlot;
amplitudePlot = _module->_amplitudePlot;
rangeMinHz = _module->_rangeMinHz;
@@ -485,10 +486,9 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
}
nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
drawBackground(args);
nvgScissor(args.vg, _insetAround, _insetAround, _size.x - _insetAround, _size.y - _insetAround);
- if (!_module || _module->isBypassed()) {
+ if (isScreenshot() || !lit) {
drawYAxis(args, strokeWidth, amplitudePlot);
drawXAxis(args, strokeWidth, frequencyPlot, rangeMinHz, rangeMaxHz);
}
@@ -524,7 +524,7 @@ void AnalyzerDisplay::draw(const DrawArgs& args) {
}
nvgRestore(args.vg);
- if (_module) {
+ if (!screenshot) {
_module->_core._channelsMutex.unlock();
}
}
diff --git a/src/analyzer_base.hpp b/src/analyzer_base.hpp
@@ -178,7 +178,7 @@ struct AnalyzerBaseWidget : BGModuleWidget {
void addAmplitudePlotContextMenu(Menu* menu, bool linearOption = true);
};
-struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
+struct AnalyzerDisplay : DisplayWidget, AnalyzerTypes {
struct BinsReader {
BinsReader() {}
virtual ~BinsReader() {}
@@ -240,7 +240,8 @@ struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
Vec size,
bool drawInset
)
- : _module(module)
+ : DisplayWidget(module)
+ , _module(module)
, _size(size)
, _graphSize(_size.x - _insetLeft - _insetRight, _size.y - _insetTop - _insetBottom)
, _drawInset(drawInset)
@@ -268,7 +269,7 @@ struct AnalyzerDisplay : TransparentWidget, AnalyzerTypes {
void setChannelBinsReaderFactory(int channel, BinsReaderFactory brf);
void displayChannel(int channel, bool display);
void channelLabel(int channel, std::string label);
- void draw(const DrawArgs& args) override;
+ void drawOnce(const DrawArgs& args, bool screenshot, bool lit) override;
void drawBackground(const DrawArgs& args);
virtual void drawHeader(const DrawArgs& args, float rangeMinHz, float rangeMaxHz);
void drawYAxis(const DrawArgs& args, float strokeWidth, AmplitudePlot plot);
diff --git a/src/mixer.cpp b/src/mixer.cpp
@@ -112,13 +112,18 @@ void MuteButton::onButton(const event::Button& e) {
}
}
+bool MuteButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
void MuteButton::draw(const DrawArgs& args) {
- nvgSave(args.vg);
- if (module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f) {
- nvgGlobalTint(args.vg, color::WHITE);
+ if (!isLit()) {
+ ToggleButton::draw(args);
}
+}
+
+void MuteButton::drawLit(const DrawArgs& args) {
ToggleButton::draw(args);
- nvgRestore(args.vg);
}
@@ -176,13 +181,20 @@ void SoloMuteButton::onChange(const event::Change& e) {
ParamWidget::onChange(e);
}
+bool SoloMuteButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
void SoloMuteButton::draw(const DrawArgs& args) {
- nvgSave(args.vg);
- if (module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f) {
- nvgGlobalTint(args.vg, color::WHITE);
+ if (!isLit() || !getParamQuantity() || getParamQuantity()->getValue() < 1.0f) {
+ ParamWidget::draw(args);
+ }
+}
+
+void SoloMuteButton::drawLit(const DrawArgs& args) {
+ if (getParamQuantity() && getParamQuantity()->getValue() >= 1.0f) {
+ ParamWidget::draw(args);
}
- ParamWidget::draw(args);
- nvgRestore(args.vg);
}
diff --git a/src/mixer.hpp b/src/mixer.hpp
@@ -71,17 +71,19 @@ struct DimmableMixerWidget : LinearCVMixerWidget {
void contextMenu(Menu* menu) override;
};
-struct MuteButton : ToggleButton {
+struct MuteButton : LightEmittingWidget<ToggleButton> {
MuteButton() {
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_0.svg")));
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_1_orange.svg")));
}
void onButton(const event::Button& e) override;
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
-struct SoloMuteButton : ParamWidget {
+struct SoloMuteButton : LightEmittingWidget<ParamWidget> {
std::vector<std::shared_ptr<Svg>> _frames;
SvgWidget* _svgWidget; // deleted elsewhere.
CircularShadow* shadow = NULL;
@@ -89,7 +91,9 @@ struct SoloMuteButton : ParamWidget {
SoloMuteButton();
void onButton(const event::Button& e) override;
void onChange(const event::Change& e) override;
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
struct DimSwitchQuantity : SwitchQuantity {
diff --git a/src/widgets.cpp b/src/widgets.cpp
@@ -6,6 +6,30 @@
using namespace bogaudio;
using namespace bogaudio::dsp;
+DisplayWidget::DisplayWidget(Module* module) : _module(module) {
+}
+
+bool DisplayWidget::isLit() {
+ return _module && !_module->isBypassed();
+}
+
+bool DisplayWidget::isScreenshot() {
+ return !_module;
+}
+
+void DisplayWidget::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ drawOnce(args, isScreenshot(), false);
+ }
+}
+
+void DisplayWidget::drawLit(const DrawArgs& args) {
+ if (isLit()) {
+ drawOnce(args, false, true);
+ }
+}
+
+
std::string SkinnableWidget::skinSVG(const std::string& base, const std::string& skin) {
std::string s = skin;
if (s == "default") {
@@ -20,6 +44,7 @@ std::string SkinnableWidget::skinSVG(const std::string& base, const std::string&
return svg;
}
+
Screw::Screw() {
skinChanged("default");
}
@@ -227,16 +252,20 @@ void IndicatorKnob::redraw() {
onChange(c);
}
-void IndicatorKnob::draw(const DrawArgs& args) {
- nvgSave(args.vg);
- if (module && !module->isBypassed() && getParamQuantity() &&
+bool IndicatorKnob::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() &&
(getParamQuantity()->getValue() < -0.01f || getParamQuantity()->getValue() > 0.01f) &&
- (!w->_drawColorsCB || w->_drawColorsCB()))
- {
- nvgGlobalTint(args.vg, color::WHITE);
+ (!w->_drawColorsCB || w->_drawColorsCB());
+}
+
+void IndicatorKnob::draw(const DrawArgs& args) {
+ if (!isLit()) {
+ Knob::draw(args);
}
+}
+
+void IndicatorKnob::drawLit(const DrawArgs& args) {
Knob::draw(args);
- nvgRestore(args.vg);
}
void IndicatorKnob::skinChanged(const std::string& skin) {
@@ -252,6 +281,7 @@ void IndicatorKnob::skinChanged(const std::string& skin) {
fb->dirty = true;
}
+
Port24::Port24() {
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, skinSVG("port").c_str())));
box.size = Vec(24, 24);
@@ -349,13 +379,18 @@ IndicatorButtonGreen9::IndicatorButtonGreen9() {
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_9px_1_green.svg")));
}
+bool IndicatorButtonGreen9::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f;
+}
+
void IndicatorButtonGreen9::draw(const DrawArgs& args) {
- nvgSave(args.vg);
- if (module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f) {
- nvgGlobalTint(args.vg, color::WHITE);
+ if (!isLit()) {
+ SvgSwitch::draw(args);
}
+}
+
+void IndicatorButtonGreen9::drawLit(const DrawArgs& args) {
SvgSwitch::draw(args);
- nvgRestore(args.vg);
}
@@ -495,15 +530,19 @@ void InvertingIndicatorButton::onChange(const event::Change& e) {
ParamWidget::onChange(e);
}
+bool InvertingIndicatorButton::isLit() {
+ return module && !module->isBypassed() && getParamQuantity() &&
+ (getParamQuantity()->getValue() < -0.01f || getParamQuantity()->getValue() > 0.01f);
+}
+
void InvertingIndicatorButton::draw(const DrawArgs& args) {
- nvgSave(args.vg);
- if (module && !module->isBypassed() && getParamQuantity() &&
- (getParamQuantity()->getValue() < -0.01f || getParamQuantity()->getValue() > 0.01f))
- {
- nvgGlobalTint(args.vg, color::WHITE);
+ if (!isLit()) {
+ ParamWidget::draw(args);
}
+}
+
+void InvertingIndicatorButton::drawLit(const DrawArgs& args) {
ParamWidget::draw(args);
- nvgRestore(args.vg);
}
@@ -521,16 +560,18 @@ NVGcolor bogaudio::decibelsToColor(float db) {
}
-void VUSlider::draw(const DrawArgs& args) {
- float level = 0.0f;
- if (getParamQuantity()) {
- level = getParamQuantity()->getValue();
- }
- else {
- float minDb = -60.0f;
- float maxDb = 6.0f;
- level = fabsf(minDb) / (maxDb - minDb);
+bool VUSlider::isLit() {
+ float db = _vuLevel ? *_vuLevel : 0.0f;
+ bool stereo = false;
+ float stereoDb = 0.0f;
+ if (_stereoVuLevel) {
+ stereo = true;
+ stereoDb = *_stereoVuLevel;
}
+ return module && !module->isBypassed() && (db > 0.0f || (stereo && stereoDb > 0.0f));
+}
+
+void VUSlider::draw(const DrawArgs& args) {
nvgSave(args.vg);
{
@@ -545,7 +586,7 @@ void VUSlider::draw(const DrawArgs& args) {
nvgSave(args.vg);
{
- nvgTranslate(args.vg, 0, (box.size.y - 13.0f) * (1.0f - level));
+ drawTranslate(args);
nvgBeginPath(args.vg);
nvgRoundedRect(args.vg, 0, 0, 18, 13, 1.5);
nvgFillColor(args.vg, nvgRGBA(0x77, 0x77, 0x77, 0xff));
@@ -565,39 +606,54 @@ void VUSlider::draw(const DrawArgs& args) {
nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
nvgFillColor(args.vg, nvgRGBA(0xaa, 0xaa, 0xaa, 0xff));
nvgFill(args.vg);
+ }
+ nvgRestore(args.vg);
+}
+
+void VUSlider::drawLit(const DrawArgs& args) {
+ float db = _vuLevel ? *_vuLevel : 0.0f;
+ bool stereo = false;
+ float stereoDb = 0.0f;
+ if (_stereoVuLevel) {
+ stereo = true;
+ stereoDb = *_stereoVuLevel;
+ }
- float db = _vuLevel ? *_vuLevel : 0.0f;
- bool stereo = false;
- float stereoDb = 0.0f;
- if (_stereoVuLevel) {
- stereo = true;
- stereoDb = *_stereoVuLevel;
+ nvgSave(args.vg);
+ drawTranslate(args);
+ if (db > 0.0f) {
+ nvgSave(args.vg);
+ nvgBeginPath(args.vg);
+ if (stereo) {
+ nvgRoundedRect(args.vg, 2, 4, stereo ? 7 : 14, 5, 1.0);
}
- if (module && !module->isBypassed()) {
- if (db > 0.0f) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
- nvgBeginPath(args.vg);
- if (stereo) {
- nvgRoundedRect(args.vg, 2, 4, stereo ? 7 : 14, 5, 1.0);
- }
- else {
- nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
- }
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(db)));
- nvgFill(args.vg);
- nvgRestore(args.vg);
- }
- if (stereo && stereoDb > 0.0f) {
- nvgSave(args.vg);
- nvgGlobalTint(args.vg, color::WHITE);
- nvgBeginPath(args.vg);
- nvgRoundedRect(args.vg, 9, 4, 7, 5, 1.0);
- nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(stereoDb)));
- nvgFill(args.vg);
- nvgRestore(args.vg);
- }
+ else {
+ nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0);
}
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(db)));
+ nvgFill(args.vg);
+ nvgRestore(args.vg);
+ }
+ if (stereo && stereoDb > 0.0f) {
+ nvgSave(args.vg);
+ nvgBeginPath(args.vg);
+ nvgRoundedRect(args.vg, 9, 4, 7, 5, 1.0);
+ nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(stereoDb)));
+ nvgFill(args.vg);
+ nvgRestore(args.vg);
}
nvgRestore(args.vg);
}
+
+void VUSlider::drawTranslate(const DrawArgs& args) {
+ float level = 0.0f;
+ if (getParamQuantity()) {
+ level = getParamQuantity()->getValue();
+ }
+ else {
+ float minDb = -60.0f;
+ float maxDb = 6.0f;
+ level = fabsf(minDb) / (maxDb - minDb);
+ }
+ nvgTranslate(args.vg, 0, (box.size.y - 13.0f) * (1.0f - level));
+}
diff --git a/src/widgets.hpp b/src/widgets.hpp
@@ -11,6 +11,32 @@ extern Plugin *pluginInstance;
namespace bogaudio {
+template <class BASE>
+struct LightEmittingWidget : BASE {
+ virtual bool isLit() = 0;
+
+ void drawLayer(const typename BASE::DrawArgs& args, int layer) override {
+ if (layer == 1 && isLit()) {
+ drawLit(args);
+ }
+ BASE::drawLayer(args, layer);
+ }
+
+ virtual void drawLit(const typename BASE::DrawArgs& args) {}
+};
+
+struct DisplayWidget : LightEmittingWidget<OpaqueWidget> {
+ Module* _module = NULL;
+
+ DisplayWidget(Module* module);
+
+ bool isLit() override;
+ virtual bool isScreenshot();
+ void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ virtual void drawOnce(const DrawArgs& args, bool screenshot, bool lit) = 0;
+};
+
struct SkinnableWidget : SkinChangeListener {
void skinChanged(const std::string& skin) override {}
std::string skinSVG(const std::string& base, const std::string& skin = "default");
@@ -59,7 +85,7 @@ struct Knob68 : BGKnob {
Knob68();
};
-struct IndicatorKnob : Knob, SkinnableWidget {
+struct IndicatorKnob : LightEmittingWidget<Knob>, SkinnableWidget {
struct IKWidget : widget::Widget {
float _angle = 0.0f;
NVGcolor _color = nvgRGBA(0x00, 0x00, 0x00, 0x00);
@@ -82,7 +108,9 @@ struct IndicatorKnob : Knob, SkinnableWidget {
inline void setDrawColorsCallback(std::function<bool()> fn) { w->_drawColorsCB = fn; }
inline void setUnipolarCallback(std::function<bool()> fn) { w->_unipolarCB = fn; }
void redraw();
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
void skinChanged(const std::string& skin) override;
};
@@ -139,12 +167,15 @@ struct ToggleButton18 : ToggleButton {
ToggleButton18();
};
-struct IndicatorButtonGreen9 : SvgSwitch {
+struct IndicatorButtonGreen9 : LightEmittingWidget<SvgSwitch> {
IndicatorButtonGreen9();
+
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
-struct InvertingIndicatorButton : ParamWidget {
+struct InvertingIndicatorButton : LightEmittingWidget<ParamWidget> {
struct IIBWidget : widget::Widget {
int _dim;
NVGcolor _color = nvgRGBA(0x00, 0x00, 0x00, 0x00);
@@ -169,7 +200,9 @@ struct InvertingIndicatorButton : ParamWidget {
void onDoubleClick(const event::DoubleClick& e) override {}
void onButton(const event::Button& e) override;
void onChange(const event::Change& e) override;
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
};
struct InvertingIndicatorButton9 : InvertingIndicatorButton {
@@ -182,7 +215,7 @@ struct InvertingIndicatorButton18 : InvertingIndicatorButton {
NVGcolor decibelsToColor(float db);
-struct VUSlider : SliderKnob {
+struct VUSlider : LightEmittingWidget<SliderKnob> {
const float slideHeight = 13.0f;
float* _vuLevel = NULL;
float* _stereoVuLevel = NULL;
@@ -197,7 +230,10 @@ struct VUSlider : SliderKnob {
inline void setStereoVULevel(float* level) {
_stereoVuLevel = level;
}
+ bool isLit() override;
void draw(const DrawArgs& args) override;
+ void drawLit(const DrawArgs& args) override;
+ void drawTranslate(const DrawArgs& args);
};
struct VUSlider151 : VUSlider {