Browse Source

Use PlugPort SVG and MediumLight from Component Library for plug (WIP).

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
d7e1dae42c
8 changed files with 324 additions and 83 deletions
  1. +1
    -0
      include/app/PortWidget.hpp
  2. +213
    -0
      res/ComponentLibrary/PlugPort.svg
  3. +74
    -55
      src/app/CableWidget.cpp
  4. +18
    -15
      src/app/PortWidget.cpp
  5. +9
    -2
      src/app/RackWidget.cpp
  6. +3
    -7
      src/engine/Module.cpp
  7. +1
    -0
      src/widget/FramebufferWidget.cpp
  8. +5
    -4
      src/widget/Widget.cpp

+ 1
- 0
include/app/PortWidget.hpp View File

@@ -39,6 +39,7 @@ struct PortWidget : widget::OpaqueWidget {
void onDragDrop(const DragDropEvent& e) override; void onDragDrop(const DragDropEvent& e) override;
void onDragEnter(const DragEnterEvent& e) override; void onDragEnter(const DragEnterEvent& e) override;
void onDragLeave(const DragLeaveEvent& e) override; void onDragLeave(const DragLeaveEvent& e) override;
void onContextDestroy(const ContextDestroyEvent& e) override;
}; };






+ 213
- 0
res/ComponentLibrary/PlugPort.svg View File

@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->

<svg
version="1.0"
id="svg15246"
x="0px"
y="0px"
width="15.8003px"
height="15.8003px"
viewBox="0 0 15.8003 15.8003"
enable-background="new 0 0 15.8003 15.8003"
xml:space="preserve"
sodipodi:docname="PlugPort.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs157" />

<linearGradient
id="SVGID_2_"
gradientUnits="userSpaceOnUse"
x1="355.22113"
y1="-3759.56128"
x2="377.73505"
y2="-3759.56128"
gradientTransform="matrix(0 1 -1 0 -4696.65137 578.8092)">
<stop
offset="0.00559"
style="stop-color:#FFFFFF"
id="stop11" />
<stop
offset="1"
style="stop-color:#454545"
id="stop13" />
</linearGradient>


<linearGradient
id="SVGID_3_"
gradientUnits="userSpaceOnUse"
x1="-8019.91748"
y1="2332.14722"
x2="-8002.08936"
y2="2332.14722"
gradientTransform="matrix(0 -1 1 0 -3269.23706 -7065.71631)">
<stop
offset="0.00559"
style="stop-color:#FFFFFF"
id="stop20" />
<stop
offset="1"
style="stop-color:#454545"
id="stop22" />
</linearGradient>



<linearGradient
id="SVGID_4_"
gradientUnits="userSpaceOnUse"
x1="-6757.92383"
y1="3834.65601"
x2="-6757.92383"
y2="3849.91846"
gradientTransform="matrix(-1 0 0 1 -7695.01367 -2897)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop31" />
<stop
offset="1"
style="stop-color:#5E5E5E"
id="stop33" />
</linearGradient>


<linearGradient
id="SVGID_5_"
gradientUnits="userSpaceOnUse"
x1="-6757.92383"
y1="3848.08325"
x2="-6757.92383"
y2="3836.49146"
gradientTransform="matrix(-1 0 0 1 -7695.01367 -2897)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop40" />
<stop
offset="1"
style="stop-color:#383636"
id="stop42" />
</linearGradient>


<sodipodi:namedview
bordercolor="#666666"
borderopacity="1.0"
fit-margin-bottom="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-top="0"
id="base"
inkscape:current-layer="svg15246"
inkscape:cx="9.7740969"
inkscape:cy="20.981046"
inkscape:document-units="mm"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-nodes="false"
inkscape:snap-others="false"
inkscape:window-height="882"
inkscape:window-maximized="0"
inkscape:window-width="1600"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:zoom="9.7707237"
pagecolor="#ffffff"
showgrid="false"
units="px"
inkscape:pagecheckerboard="0">
</sodipodi:namedview>




<linearGradient
id="SVGID_11_"
gradientUnits="userSpaceOnUse"
x1="-8066.65869"
y1="2299.03101"
x2="-8048.83008"
y2="2299.03101"
gradientTransform="matrix(0 -1 1 0 -3269.23706 -7065.71631)">
<stop
offset="0"
style="stop-color:#8C8B8B"
id="stop93" />
<stop
offset="1"
style="stop-color:#454545"
id="stop95" />
</linearGradient>






<linearGradient
id="SVGID_16_"
gradientUnits="userSpaceOnUse"
x1="-2831.54297"
y1="3096.30811"
x2="-2831.54297"
y2="3080.50781"
gradientTransform="matrix(1 0 0 1 2839.44287 -3080.50781)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop138" />
<stop
offset="1"
style="stop-color:#0A0A0A"
id="stop140" />
</linearGradient>
<circle
opacity="0.32"
fill="url(#SVGID_16_)"
cx="7.90013"
cy="7.90013"
r="7.90013"
id="circle143" />
<circle
fill="#E0E0E0"
cx="7.90013"
cy="7.90013"
r="6.46479"
id="circle145" />
<linearGradient
id="SVGID_17_"
gradientUnits="userSpaceOnUse"
x1="-2802.25293"
y1="3043.80615"
x2="-2813.42529"
y2="3043.80615"
gradientTransform="matrix(-3.491481e-15 1 -1 -3.491481e-15 3051.7063 2815.73926)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop147" />
<stop
offset="1"
style="stop-color:#706C6C"
id="stop149" />
</linearGradient>
<circle
fill="url(#SVGID_17_)"
cx="7.90013"
cy="7.90013"
r="5.58624"
id="circle152" />
<circle
cx="7.90013"
cy="7.90013"
r="4.82294"
id="circle154" />
</svg>

+ 74
- 55
src/app/CableWidget.cpp View File

@@ -4,6 +4,7 @@
#include <window.hpp> #include <window.hpp>
#include <context.hpp> #include <context.hpp>
#include <patch.hpp> #include <patch.hpp>
#include <asset.hpp>
#include <settings.hpp> #include <settings.hpp>
#include <engine/Engine.hpp> #include <engine/Engine.hpp>
#include <engine/Port.hpp> #include <engine/Port.hpp>
@@ -13,12 +14,20 @@ namespace rack {
namespace app { namespace app {




struct CableWidget::Internal {
std::shared_ptr<Svg> plugPortSvg;
};


CableWidget::CableWidget() { CableWidget::CableWidget() {
internal = new Internal;
color = color::BLACK_TRANSPARENT; color = color::BLACK_TRANSPARENT;
internal->plugPortSvg = Svg::load(asset::system("res/ComponentLibrary/PlugPort.svg"));
} }


CableWidget::~CableWidget() { CableWidget::~CableWidget() {
setCable(NULL); setCable(NULL);
delete internal;
} }


void CableWidget::setNextCableColor() { void CableWidget::setNextCableColor() {
@@ -115,36 +124,43 @@ void CableWidget::fromJson(json_t* rootJ) {
} }
} }


static void drawPlug(NVGcontext* vg, math::Vec pos, NVGcolor color) {
static void CableWidget_drawPlug(CableWidget* that, const widget::Widget::DrawArgs& args, math::Vec pos, NVGcolor color, bool top) {
if (!top)
return;

NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5);
nvgSave(args.vg);
nvgTranslate(args.vg, pos.x, pos.y);


// Plug solid // Plug solid
nvgBeginPath(vg);
nvgCircle(vg, pos.x, pos.y, 9);
nvgFillColor(vg, color);
nvgFill(vg);
nvgBeginPath(args.vg);
nvgCircle(args.vg, 0.0, 0.0, 9);
nvgFillColor(args.vg, color);
nvgFill(args.vg);


// Border // Border
nvgStrokeWidth(vg, 1.0);
nvgStrokeColor(vg, colorOutline);
nvgStroke(vg);

// Hole
nvgBeginPath(vg);
nvgCircle(vg, pos.x, pos.y, 5);
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0));
nvgFill(vg);
nvgStrokeWidth(args.vg, 1.0);
nvgStrokeColor(args.vg, colorOutline);
nvgStroke(args.vg);

// Port
std::shared_ptr<Svg> plugPortSvg = that->internal->plugPortSvg;
math::Vec plugPortSize = plugPortSvg->getSize();
nvgTranslate(args.vg, VEC_ARGS(plugPortSize.div(2).neg()));
plugPortSvg->draw(args.vg);

nvgRestore(args.vg);
} }


static void drawCable(NVGcontext* vg, math::Vec pos1, math::Vec pos2, NVGcolor color, float thickness, float tension, float opacity) {
static void CableWidget_drawCable(CableWidget* that, const widget::Widget::DrawArgs& args, math::Vec pos1, math::Vec pos2, NVGcolor color, float thickness, float tension, float opacity) {
NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.10); NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.10);
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5);


// Cable // Cable
if (opacity > 0.0) { if (opacity > 0.0) {
nvgSave(vg);
nvgSave(args.vg);
// This power scaling looks more linear than actual linear scaling // This power scaling looks more linear than actual linear scaling
nvgGlobalAlpha(vg, std::pow(opacity, 1.5));
nvgGlobalAlpha(args.vg, std::pow(opacity, 1.5));


float dist = pos1.minus(pos2).norm(); float dist = pos1.minus(pos2).norm();
math::Vec slump; math::Vec slump;
@@ -155,31 +171,31 @@ static void drawCable(NVGcontext* vg, math::Vec pos1, math::Vec pos2, NVGcolor c
pos1 = pos1.plus(pos3.minus(pos1).normalize().mult(9)); pos1 = pos1.plus(pos3.minus(pos1).normalize().mult(9));
pos2 = pos2.plus(pos3.minus(pos2).normalize().mult(9)); pos2 = pos2.plus(pos3.minus(pos2).normalize().mult(9));


nvgLineJoin(vg, NVG_ROUND);
nvgLineJoin(args.vg, NVG_ROUND);


// Shadow // Shadow
math::Vec pos4 = pos3.plus(slump.mult(0.08)); math::Vec pos4 = pos3.plus(slump.mult(0.08));
nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorShadow);
nvgStrokeWidth(vg, thickness);
nvgStroke(vg);
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, pos1.x, pos1.y);
nvgQuadTo(args.vg, pos4.x, pos4.y, pos2.x, pos2.y);
nvgStrokeColor(args.vg, colorShadow);
nvgStrokeWidth(args.vg, thickness);
nvgStroke(args.vg);


// Cable outline // Cable outline
nvgBeginPath(vg);
nvgMoveTo(vg, pos1.x, pos1.y);
nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y);
nvgStrokeColor(vg, colorOutline);
nvgStrokeWidth(vg, thickness);
nvgStroke(vg);
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, pos1.x, pos1.y);
nvgQuadTo(args.vg, pos3.x, pos3.y, pos2.x, pos2.y);
nvgStrokeColor(args.vg, colorOutline);
nvgStrokeWidth(args.vg, thickness);
nvgStroke(args.vg);


// Cable solid // Cable solid
nvgStrokeColor(vg, color);
nvgStrokeWidth(vg, thickness - 2);
nvgStroke(vg);
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, thickness - 2);
nvgStroke(args.vg);


nvgRestore(vg);
nvgRestore(args.vg);
} }
} }


@@ -212,33 +228,36 @@ void CableWidget::draw(const DrawArgs& args) {


math::Vec outputPos = getOutputPos(); math::Vec outputPos = getOutputPos();
math::Vec inputPos = getInputPos(); math::Vec inputPos = getInputPos();
drawCable(args.vg, outputPos, inputPos, color, thickness, tension, opacity);
CableWidget_drawCable(this, args, outputPos, inputPos, color, thickness, tension, opacity);
} }


void CableWidget::drawPlugs(const DrawArgs& args) { void CableWidget::drawPlugs(const DrawArgs& args) {
// Draw output plug
math::Vec outputPos = getOutputPos(); math::Vec outputPos = getOutputPos();
math::Vec inputPos = getInputPos();

// Draw plug if the cable is on top, or if the cable is incomplete
if (!isComplete() || APP->scene->rack->getTopCable(outputPort) == this) {
drawPlug(args.vg, outputPos, color);
if (isComplete()) {
// Draw plug light
nvgSave(args.vg);
nvgTranslate(args.vg, outputPos.x - 4, outputPos.y - 4);
outputPort->getPlugLight()->draw(args);
nvgRestore(args.vg);
}
bool outputTop = !isComplete() || APP->scene->rack->getTopCable(outputPort) == this;
CableWidget_drawPlug(this, args, outputPos, color, outputTop);
if (outputTop && isComplete()) {
// Draw output plug light
nvgSave(args.vg);
LightWidget* plugLight = outputPort->getPlugLight();
math::Vec plugPos = outputPos.minus(plugLight->getSize().div(2));
nvgTranslate(args.vg, VEC_ARGS(plugPos));
plugLight->draw(args);
nvgRestore(args.vg);
} }


if (!isComplete() || APP->scene->rack->getTopCable(inputPort) == this) {
drawPlug(args.vg, inputPos, color);
if (isComplete()) {
nvgSave(args.vg);
nvgTranslate(args.vg, inputPos.x - 4, inputPos.y - 4);
inputPort->getPlugLight()->draw(args);
nvgRestore(args.vg);
}
// Draw input plug
math::Vec inputPos = getInputPos();
bool inputTop = !isComplete() || APP->scene->rack->getTopCable(inputPort) == this;
CableWidget_drawPlug(this, args, inputPos, color, inputTop);
if (inputTop && isComplete()) {
// Draw input plug light
nvgSave(args.vg);
LightWidget* plugLight = inputPort->getPlugLight();
math::Vec plugPos = inputPos.minus(plugLight->getSize().div(2));
nvgTranslate(args.vg, VEC_ARGS(plugPos));
plugLight->draw(args);
nvgRestore(args.vg);
} }
} }




+ 18
- 15
src/app/PortWidget.cpp View File

@@ -63,36 +63,33 @@ struct PortTooltip : ui::Tooltip {
}; };




struct PlugLight : MultiLightWidget {
PlugLight() {
addBaseColor(componentlibrary::SCHEME_GREEN);
addBaseColor(componentlibrary::SCHEME_RED);
addBaseColor(componentlibrary::SCHEME_BLUE);
box.size = math::Vec(8, 8);
bgColor = componentlibrary::SCHEME_BLACK_TRANSPARENT;
}
};


struct PortWidget::Internal { struct PortWidget::Internal {
ui::Tooltip* tooltip = NULL; ui::Tooltip* tooltip = NULL;
PlugLight* plugLight;
app::MultiLightWidget* plugLight;
}; };




PortWidget::PortWidget() { PortWidget::PortWidget() {
internal = new Internal; internal = new Internal;

using namespace componentlibrary;
struct PlugLight : TRedGreenBlueLight<TGrayModuleLightWidget<MediumLight<app::MultiLightWidget>>> {
PlugLight() {
// fb->bypassed = true;
fb->oversample = 1.0;
}
};
internal->plugLight = new PlugLight; internal->plugLight = new PlugLight;
} }


PortWidget::~PortWidget() { PortWidget::~PortWidget() {
// The port shouldn't have any cables when destroyed, but just to make sure.
if (module)
APP->scene->rack->clearCablesOnPort(this);
// HACK: In case onDragDrop() is called but not onLeave() afterwards... // HACK: In case onDragDrop() is called but not onLeave() afterwards...
destroyTooltip(); destroyTooltip();
// plugLight is not a child but owned by the PortWidget, so we need to delete it here // plugLight is not a child but owned by the PortWidget, so we need to delete it here
delete internal->plugLight; delete internal->plugLight;
// The port shouldn't have any cables when destroyed, but just to make sure.
if (module)
APP->scene->rack->clearCablesOnPort(this);
delete internal; delete internal;
} }


@@ -151,6 +148,7 @@ void PortWidget::step() {
values[i] = module->inputs[portId].plugLights[i].getBrightness(); values[i] = module->inputs[portId].plugLights[i].getBrightness();
} }
internal->plugLight->setBrightnesses(values); internal->plugLight->setBrightnesses(values);
internal->plugLight->step();


Widget::step(); Widget::step();
} }
@@ -336,6 +334,11 @@ void PortWidget::onDragLeave(const DragLeaveEvent& e) {
} }
} }


void PortWidget::onContextDestroy(const ContextDestroyEvent& e) {
internal->plugLight->onContextDestroy(e);
Widget::onContextDestroy(e);
}



} // namespace app } // namespace app
} // namespace rack } // namespace rack

+ 9
- 2
src/app/RackWidget.cpp View File

@@ -60,7 +60,11 @@ struct CableContainer : widget::TransparentWidget {
for (widget::Widget* w : children) { for (widget::Widget* w : children) {
CableWidget* cw = dynamic_cast<CableWidget*>(w); CableWidget* cw = dynamic_cast<CableWidget*>(w);
assert(cw); assert(cw);
cw->drawPlugs(args);

DrawArgs childArgs = args;
// TODO Make clip box equal actual viewport
childArgs.clipBox = math::Rect::inf();
cw->drawPlugs(childArgs);
} }


Widget::draw(args); Widget::draw(args);
@@ -433,6 +437,7 @@ void RackWidget::removeModule(ModuleWidget* m) {
bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) { bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) {
// Check intersection with other modules // Check intersection with other modules
math::Rect mwBox = math::Rect(pos, mw->box.size); math::Rect mwBox = math::Rect(pos, mw->box.size);
mwBox.size.x -= 0.01;
for (widget::Widget* w2 : moduleContainer->children) { for (widget::Widget* w2 : moduleContainer->children) {
// Don't intersect with self // Don't intersect with self
if (mw == w2) if (mw == w2)
@@ -441,7 +446,9 @@ bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) {
if (!w2->visible) if (!w2->visible)
continue; continue;
// Check intersection // Check intersection
if (mwBox.intersects(w2->box))
math::Rect w2Box = w2->box;
w2Box.size.x -= 0.01;
if (mwBox.intersects(w2Box))
return false; return false;
} }




+ 3
- 7
src/engine/Module.cpp View File

@@ -315,16 +315,12 @@ static void Port_step(Port* that, float deltaTime) {
} }
else if (that->channels == 1) { else if (that->channels == 1) {
float v = that->getVoltage() / 10.f; float v = that->getVoltage() / 10.f;
that->plugLights[0].setSmoothBrightness(v, deltaTime);
that->plugLights[1].setSmoothBrightness(-v, deltaTime);
that->plugLights[0].setSmoothBrightness(-v, deltaTime);
that->plugLights[1].setSmoothBrightness(v, deltaTime);
that->plugLights[2].setBrightness(0.f); that->plugLights[2].setBrightness(0.f);
} }
else { else {
float v2 = 0.f;
for (int c = 0; c < that->channels; c++) {
v2 += std::pow(that->getVoltage(c), 2);
}
float v = std::sqrt(v2) / 10.f;
float v = that->getVoltageRMS() / 10.f;
that->plugLights[0].setBrightness(0.f); that->plugLights[0].setBrightness(0.f);
that->plugLights[1].setBrightness(0.f); that->plugLights[1].setBrightness(0.f);
that->plugLights[2].setSmoothBrightness(v, deltaTime); that->plugLights[2].setSmoothBrightness(v, deltaTime);


+ 1
- 0
src/widget/FramebufferWidget.cpp View File

@@ -105,6 +105,7 @@ void FramebufferWidget::step() {
// Create a framebuffer // Create a framebuffer
if (internal->fbSize.isFinite() && !internal->fbSize.isZero()) { if (internal->fbSize.isFinite() && !internal->fbSize.isZero()) {
internal->fb = nvgluCreateFramebuffer(vg, internal->fbSize.x, internal->fbSize.y, 0); internal->fb = nvgluCreateFramebuffer(vg, internal->fbSize.x, internal->fbSize.y, 0);
// DEBUG("Created framebuffer of size (%f, %f)", VEC_ARGS(internal->fbSize));
} }
} }
if (!internal->fb) { if (!internal->fb) {


+ 5
- 4
src/widget/Widget.cpp View File

@@ -268,15 +268,16 @@ void Widget::draw(const DrawArgs& args) {
if (!args.clipBox.intersects(child->box)) if (!args.clipBox.intersects(child->box))
continue; continue;


DrawArgs childCtx = args;
DrawArgs childArgs = args;
// Intersect child clip box with self // Intersect child clip box with self
childCtx.clipBox = childCtx.clipBox.intersect(child->box);
childCtx.clipBox.pos = childCtx.clipBox.pos.minus(child->box.pos);
childArgs.clipBox = childArgs.clipBox.intersect(child->box);
// Offset clip box by child pos
childArgs.clipBox.pos = childArgs.clipBox.pos.minus(child->box.pos);


nvgSave(args.vg); nvgSave(args.vg);
nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y); nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y);


child->draw(childCtx);
child->draw(childArgs);


#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"


Loading…
Cancel
Save