From 70bb8c7759438b097536cccee28b0ded41828a95 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 16 Nov 2017 20:45:32 -0500 Subject: [PATCH] Add plug lights, remove plug light toggling --- include/app.hpp | 54 +++++++++++++++++++---------------- include/components.hpp | 30 +++++++++---------- include/engine.hpp | 24 +++++++++------- include/rack.hpp | 4 +-- src/app/ColorLightWidget.cpp | 27 ------------------ src/app/ModuleLightWidget.cpp | 22 ++++++++++++++ src/app/MultiLightWidget.cpp | 24 ++++++++++++++++ src/app/Port.cpp | 32 +++++++++++++++++++++ src/app/Toolbar.cpp | 10 ------- src/app/WireWidget.cpp | 39 ++++++++++--------------- src/engine.cpp | 19 +++++++++++- src/settings.cpp | 9 ------ 12 files changed, 171 insertions(+), 123 deletions(-) delete mode 100644 src/app/ColorLightWidget.cpp create mode 100644 src/app/ModuleLightWidget.cpp create mode 100644 src/app/MultiLightWidget.cpp diff --git a/include/app.hpp b/include/app.hpp index 0790a2d3..5acb6bef 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -277,6 +277,33 @@ struct MomentarySwitch : virtual Switch { } }; +//////////////////// +// lights +//////////////////// + +struct LightWidget : TransparentWidget { + NVGcolor bgColor = nvgRGBf(0, 0, 0); + NVGcolor color = nvgRGBf(1, 1, 1); + void draw(NVGcontext *vg) override; +}; + +/** Mixes a list of colors based on a list of brightness values */ +struct MultiLightWidget : LightWidget { + std::vector baseColors; + void addBaseColor(NVGcolor baseColor); + /** Sets the color to a linear combination of the baseColors with the given weights */ + void setValues(const std::vector &values); +}; + +/** A MultiLightWidget that points to a module's Light or a range of lights +Will access firstLightId, firstLightId + 1, etc. for each added color +*/ +struct ModuleLightWidget : MultiLightWidget { + Module *module = NULL; + int firstLightId; + void step() override; +}; + //////////////////// // ports //////////////////// @@ -290,8 +317,11 @@ struct Port : OpaqueWidget { Module *module = NULL; PortType type = INPUT; int portId; + MultiLightWidget *plugLight; + Port(); ~Port(); + void step() override; void draw(NVGcontext *vg) override; void onMouseDown(EventMouseDown &e) override; void onDragStart(EventDragStart &e) override; @@ -315,29 +345,6 @@ 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 colors; - void addColor(NVGcolor c); - void step() override; -}; - //////////////////// // scene //////////////////// @@ -347,7 +354,6 @@ struct Toolbar : OpaqueWidget { Slider *wireTensionSlider; Slider *zoomSlider; RadioButton *cpuUsageButton; - RadioButton *plugLightButton; Toolbar(); void draw(NVGcontext *vg) override; diff --git a/include/components.hpp b/include/components.hpp index 40849dff..c300e44b 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -368,43 +368,43 @@ struct CL1362Port : SVGPort { // Lights //////////////////// -struct RedLight : ColorLightWidget { +struct RedLight : ModuleLightWidget { RedLight() { - addColor(COLOR_RED); + addBaseColor(COLOR_RED); } }; -struct GreenLight : ColorLightWidget { +struct GreenLight : ModuleLightWidget { GreenLight() { - addColor(COLOR_GREEN); + addBaseColor(COLOR_GREEN); } }; -struct YellowLight : ColorLightWidget { +struct YellowLight : ModuleLightWidget { YellowLight() { - addColor(COLOR_YELLOW); + addBaseColor(COLOR_YELLOW); } }; -struct BlueLight : ColorLightWidget { +struct BlueLight : ModuleLightWidget { BlueLight() { - addColor(COLOR_BLUE); + addBaseColor(COLOR_BLUE); } }; /** Reads two adjacent lightIds, so `lightId` and `lightId + 1` must be defined */ -struct GreenRedLight : ColorLightWidget { +struct GreenRedLight : ModuleLightWidget { GreenRedLight() { - addColor(COLOR_GREEN); - addColor(COLOR_RED); + addBaseColor(COLOR_GREEN); + addBaseColor(COLOR_RED); } }; -struct RedGreenBlueLight : ColorLightWidget { +struct RedGreenBlueLight : ModuleLightWidget { RedGreenBlueLight() { - addColor(COLOR_RED); - addColor(COLOR_GREEN); - addColor(COLOR_BLUE); + addBaseColor(COLOR_RED); + addBaseColor(COLOR_GREEN); + addBaseColor(COLOR_BLUE); } }; diff --git a/include/engine.hpp b/include/engine.hpp index 2f0bc546..ad3cf9e5 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -11,11 +11,22 @@ struct Param { float value = 0.0; }; +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); +}; + struct Input { /** Voltage of the port, zero if not plugged in. Read-only by Module */ float value = 0.0; /** Whether a wire is plugged in */ bool active = false; + Light plugLights[2]; /** Returns the value if a wire is plugged in, otherwise returns the given default value */ float normalize(float normalValue) { return active ? value : normalValue; @@ -27,16 +38,7 @@ struct Output { float value = 0.0; /** Whether a wire is plugged in */ bool active = false; -}; - -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); + Light plugLights[2]; }; @@ -49,7 +51,7 @@ struct Module { float cpuTime = 0.0; /** Deprecated, use constructor below this one */ - Module() {} + Module() DEPRECATED {} /** Constructs Module with a fixed number of params, inputs, and outputs */ Module(int numParams, int numInputs, int numOutputs, int numLights = 0) { params.resize(numParams); diff --git a/include/rack.hpp b/include/rack.hpp index 5d45a5e5..b4371009 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -74,11 +74,11 @@ Port *createOutput(Vec pos, Module *module, int outputId) { } template -ModuleLightWidget *createLight(Vec pos, Module *module, int lightId) { +ModuleLightWidget *createLight(Vec pos, Module *module, int firstLightId) { ModuleLightWidget *light = new TModuleLightWidget(); light->box.pos = pos; light->module = module; - light->lightId = lightId; + light->firstLightId = firstLightId; return light; } diff --git a/src/app/ColorLightWidget.cpp b/src/app/ColorLightWidget.cpp deleted file mode 100644 index 125373b2..00000000 --- a/src/app/ColorLightWidget.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "app.hpp" -#include "engine.hpp" - - -namespace rack { - - -void ColorLightWidget::addColor(NVGcolor c) { - colors.push_back(c); -} - -void ColorLightWidget::step() { - assert(module); - assert(module->lights.size() >= lightId + colors.size()); - 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(); - brightness = clampf(brightness, 0.0, 1.0); - color.r += c.r * brightness; - color.g += c.g * brightness; - color.b += c.b * brightness; - } -} - - -} // namespace rack diff --git a/src/app/ModuleLightWidget.cpp b/src/app/ModuleLightWidget.cpp new file mode 100644 index 00000000..02296a0d --- /dev/null +++ b/src/app/ModuleLightWidget.cpp @@ -0,0 +1,22 @@ +#include "app.hpp" +#include "engine.hpp" + + +namespace rack { + + +void ModuleLightWidget::step() { + assert(module); + assert(module->lights.size() >= firstLightId + baseColors.size()); + std::vector values(baseColors.size()); + + for (size_t i = 0; i < baseColors.size(); i++) { + float value = module->lights[firstLightId + i].getBrightness(); + value = clampf(value, 0.0, 1.0); + values[i] = value; + } + setValues(values); +} + + +} // namespace rack diff --git a/src/app/MultiLightWidget.cpp b/src/app/MultiLightWidget.cpp new file mode 100644 index 00000000..eb9ceb1f --- /dev/null +++ b/src/app/MultiLightWidget.cpp @@ -0,0 +1,24 @@ +#include "app.hpp" + + +namespace rack { + + +void MultiLightWidget::addBaseColor(NVGcolor baseColor) { + baseColors.push_back(baseColor); +} + +void MultiLightWidget::setValues(const std::vector &values) { + assert(values.size() == baseColors.size()); + color = nvgRGBf(0, 0, 0); + for (size_t i = 0; i < baseColors.size(); i++) { + NVGcolor c = baseColors[i]; + float value = values[i]; + color.r += c.r * value; + color.g += c.g * value; + color.b += c.b * value; + } +} + + +} // namespace rack diff --git a/src/app/Port.cpp b/src/app/Port.cpp index 0f1e5ae0..af1cdb43 100644 --- a/src/app/Port.cpp +++ b/src/app/Port.cpp @@ -1,13 +1,45 @@ #include "app.hpp" #include "gui.hpp" +#include "components.hpp" +#include "engine.hpp" namespace rack { + +struct PlugLight : MultiLightWidget { + PlugLight() { + addBaseColor(COLOR_GREEN); + addBaseColor(COLOR_RED); + box.size = Vec(8, 8); + bgColor = COLOR_BLACK_TRANSPARENT; + } +}; + + +Port::Port() { + plugLight = new PlugLight(); +} + Port::~Port() { + // plugLight is not a child and is thus owned by the Port, so we need to delete it here + delete plugLight; gRackWidget->wireContainer->removeAllWires(this); } +void Port::step() { + std::vector values(2); + if (type == INPUT) { + values[0] = module->inputs[portId].plugLights[0].getBrightness(); + values[1] = module->inputs[portId].plugLights[1].getBrightness(); + } + else { + values[0] = module->outputs[portId].plugLights[0].getBrightness(); + values[1] = module->outputs[portId].plugLights[1].getBrightness(); + } + plugLight->setValues(values); +} + void Port::draw(NVGcontext *vg) { WireWidget *activeWire = gRackWidget->wireContainer->activeWire; if (activeWire) { diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index 15138ea3..cde1221b 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -166,16 +166,6 @@ Toolbar::Toolbar() { } xPos += margin; - { - plugLightButton = new RadioButton(); - plugLightButton->box.pos = Vec(xPos, margin); - plugLightButton->box.size.x = 100; - plugLightButton->label = "Plug lights"; - addChild(plugLightButton); - xPos += plugLightButton->box.size.x; - } - xPos += margin; - /* { cpuUsageButton = new RadioButton(); diff --git a/src/app/WireWidget.cpp b/src/app/WireWidget.cpp index 1908f5ac..07d16226 100644 --- a/src/app/WireWidget.cpp +++ b/src/app/WireWidget.cpp @@ -155,7 +155,9 @@ void WireWidget::draw(NVGcontext *vg) { if (!(inputPort && outputPort)) opacity = 1.0; - drawWire(vg, getOutputPos(), getInputPos(), color, tension, opacity); + Vec outputPos = getOutputPos(); + Vec inputPos = getInputPos(); + drawWire(vg, outputPos, inputPos, color, tension, opacity); } void WireWidget::drawPlugs(NVGcontext *vg) { @@ -166,31 +168,20 @@ 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]; - float value = output.value / 8.0; - outputLight->box.size = Vec(10, 10); - inputLight->box.size = Vec(10, 10); - outputLight->box.pos = outputPos.minus(Vec(5, 5)); - inputLight->box.pos = inputPos.minus(Vec(5, 5)); - outputLight->setValue(value); - inputLight->setValue(value); - } - else { - outputLight->setValue(0.0); - inputLight->setValue(0.0); - } - outputLight->visible = true; - inputLight->visible = true; + // TODO + // Only draw this when light is on top of the plug stack + if (outputPort) { + nvgSave(vg); + nvgTranslate(vg, outputPos.x - 4, outputPos.y - 4); + outputPort->plugLight->draw(vg); + nvgRestore(vg); } - else { - outputLight->visible = false; - inputLight->visible = false; + if (inputPort) { + nvgSave(vg); + nvgTranslate(vg, inputPos.x - 4, inputPos.y - 4); + inputPort->plugLight->draw(vg); + nvgRestore(vg); } - */ - Widget::draw(vg); } diff --git a/src/engine.cpp b/src/engine.cpp index 2e8f984e..d7097e4b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -39,7 +39,7 @@ float Light::getBrightness() { } void Light::setBrightnessSmooth(float brightness) { - float v = brightness * brightness; + float v = (brightness > 0.0) ? brightness * brightness : 0.0; if (v < value) { // Fade out light with lambda = 2 * framerate value += (v - value) * sampleTime * (60.0 * 2.0); @@ -87,6 +87,23 @@ static void engineStep() { // Step modules for (Module *module : modules) { module->step(); + + // TODO skip this step when plug lights are disabled + // Step ports + for (Input &input : module->inputs) { + if (input.active) { + float value = input.value / 10.0; + input.plugLights[0].setBrightnessSmooth(value); + input.plugLights[1].setBrightnessSmooth(-value); + } + } + for (Output &output : module->outputs) { + if (output.active) { + float value = output.value / 10.0; + output.plugLights[0].setBrightnessSmooth(value); + output.plugLights[1].setBrightnessSmooth(-value); + } + } } // Step cables by moving their output values to inputs diff --git a/src/settings.cpp b/src/settings.cpp index 4425e076..1020f192 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -52,10 +52,6 @@ static json_t *settingsToJson() { json_t *sampleRateJ = json_real(engineGetSampleRate()); json_object_set_new(rootJ, "sampleRate", sampleRateJ); - // plugLight - json_t *plugLightJ = json_boolean(gToolbar->plugLightButton->value > 0.0); - json_object_set_new(rootJ, "plugLight", plugLightJ); - // lastPath json_t *lastPathJ = json_string(gRackWidget->lastPath.c_str()); json_object_set_new(rootJ, "lastPath", lastPathJ); @@ -114,11 +110,6 @@ static void settingsFromJson(json_t *rootJ) { engineSetSampleRate(sampleRate); } - // plugLight - json_t *plugLightJ = json_object_get(rootJ, "plugLight"); - if (plugLightJ) - gToolbar->plugLightButton->setValue(json_is_true(plugLightJ) ? 1.0 : 0.0); - // lastPath json_t *lastPathJ = json_object_get(rootJ, "lastPath"); if (lastPathJ)