Browse Source

Add Pyer's plug SVG to CableWidget. WIP cable appearance.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
c49ea7f0f3
2 changed files with 303 additions and 63 deletions
  1. +231
    -0
      res/ComponentLibrary/Plug.svg
  2. +72
    -63
      src/app/CableWidget.cpp

+ 231
- 0
res/ComponentLibrary/Plug.svg View File

@@ -0,0 +1,231 @@
<?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="44.6px"
height="44.6px"
viewBox="0 0 44.6 44.6"
enable-background="new 0 0 44.6 44.6"
xml:space="preserve"
sodipodi:docname="Plug.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="defs174">
<linearGradient
id="SVGID_16_"
gradientUnits="userSpaceOnUse"
x1="-2860.0071"
y1="3102.7915"
x2="-2844.2068"
y2="3102.7915"
gradientTransform="rotate(-90,-2955.1582,125.35327)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop144" />
<stop
offset="1"
style="stop-color:#0A0A0A"
id="stop146" />
</linearGradient>
<linearGradient
id="SVGID_17_"
gradientUnits="userSpaceOnUse"
x1="-2857.6931"
y1="3102.7915"
x2="-2846.5205"
y2="3102.7915"
gradientTransform="rotate(-90,-2955.1582,125.35327)">
<stop
offset="0"
style="stop-color:#FFFEFE"
id="stop153" />
<stop
offset="1"
style="stop-color:#706C6C"
id="stop155" />
</linearGradient>
<linearGradient
id="SVGID_18_"
gradientUnits="userSpaceOnUse"
x1="77.863533"
y1="-41.38039"
x2="35.242031"
y2="-41.38039"
gradientTransform="matrix(0.70711,0.70711,-0.70711,0.70711,-40.89075,45.71848)">
<stop
offset="0.84358"
style="stop-color:#0A0A0A;stop-opacity:0"
id="stop164" />
<stop
offset="1"
style="stop-color:#0A0A0A"
id="stop166" />
</linearGradient>
</defs>

<linearGradient
id="SVGID_2_"
gradientUnits="userSpaceOnUse"
x1="365.67114"
y1="-3725.41138"
x2="388.18506"
y2="-3725.41138"
gradientTransform="matrix(0 1 -1 0 -4652.05127 602.50922)">
<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="-8009.46777"
y1="2366.29712"
x2="-7991.63916"
y2="2366.29712"
gradientTransform="matrix(0 -1 1 0 -3292.93701 -7021.11621)">
<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="-6747.47412"
y1="3868.80615"
x2="-6747.47412"
y2="3884.0686"
gradientTransform="matrix(-1 0 0 1 -7674.11377 -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="-6747.47412"
y1="3882.23315"
x2="-6747.47412"
y2="3870.64136"
gradientTransform="matrix(-1 0 0 1 -7674.11377 -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="12.608857"
inkscape:cy="35.393282"
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="1"
inkscape:window-width="1600"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:zoom="9.0412639"
pagecolor="#ffffff"
showgrid="false"
units="px"
inkscape:pagecheckerboard="0">
<inkscape:grid
type="xygrid"
id="grid1322" /></sodipodi:namedview>




<linearGradient
id="SVGID_11_"
gradientUnits="userSpaceOnUse"
x1="-8056.2085"
y1="2333.18091"
x2="-8038.38037"
y2="2333.18091"
gradientTransform="matrix(0 -1 1 0 -3292.93701 -7021.11621)">
<stop
offset="0"
style="stop-color:#8C8B8B"
id="stop93" />
<stop
offset="1"
style="stop-color:#454545"
id="stop95" />
</linearGradient>






<path
fill="#b2b2b2"
d="m 26.7804,36.94069 h 0.0052 l 9e-5,-0.05378 c 0,0 4e-5,5e-5 0,0 l -1.3e-4,-4.76619 c 1.13619,-0.5211 2.20487,-1.23709 3.14055,-2.17277 4.22279,-4.22279 4.22279,-11.06926 -4e-5,-15.29209 -4.22279,-4.22279 -11.0693,-4.22283 -15.29209,-4e-5 -4.22287,4.22287 -4.22283,11.06939 -4e-5,15.29218 0.93563,0.93563 2.00432,1.65163 3.14046,2.17268 l 4e-5,4.81997 h 0.0052 c 0.01346,1.13506 0.44837,2.2662 1.31443,3.13226 1.75957,1.75957 4.61234,1.75957 6.3719,0 0.86609,-0.86611 1.30104,-1.99729 1.31447,-3.13222 z"
id="path138"
style="fill:#ffffff;fill-opacity:1" /><g
opacity="0.2"
id="g142">
<path
d="m 22.27995,11.98875 c 2.75478,10e-6 5.34464,1.07277 7.29253,3.02066 1.94791,1.94791 3.02068,4.53778 3.02069,7.29251 0,2.75473 -1.07276,5.34458 -3.02065,7.29247 -0.85558,0.85558 -1.8634,1.55265 -2.99544,2.07185 l -0.29157,0.13372 2e-5,0.32077 1.1e-4,4.37332 -0.0052,0.44072 c -0.01249,1.05491 -0.42732,2.04383 -1.16808,2.78459 -0.75657,0.75656 -1.76247,1.17322 -2.8324,1.17322 -1.06993,0 -2.07582,-0.41666 -2.8324,-1.17322 -0.74069,-0.7407 -1.1555,-1.72964 -1.16802,-2.78464 l -0.0051,-0.23035 -5e-5,-4.58371 V 31.7999 l -0.29157,-0.13371 c -1.13198,-0.51915 -2.13976,-1.21618 -2.99533,-2.07174 -1.9479,-1.9479 -3.02066,-4.53777 -3.02066,-7.29251 0,-2.75476 1.07277,-5.34464 3.02069,-7.29257 1.9479,-1.94789 4.53775,-3.02063 7.29247,-3.02062 m 0,-0.50001 c -2.76733,-10e-6 -5.53461,1.05568 -7.64601,3.16708 -4.22287,4.22287 -4.22283,11.06939 -3e-5,15.29218 0.93563,0.93562 2.00431,1.65162 3.14045,2.17267 l 5e-5,4.81998 h 0.0052 c 0.01346,1.13506 0.44837,2.2662 1.31443,3.13226 0.87978,0.87978 2.03287,1.31967 3.18595,1.31967 1.15308,0 2.30617,-0.43989 3.18595,-1.31967 0.86611,-0.86611 1.30105,-1.99729 1.31448,-3.13222 h 0.0052 l 8e-5,-0.05378 -1.3e-4,-4.76619 c 1.13618,-0.5211 2.20486,-1.2371 3.14055,-2.17277 4.22279,-4.22279 4.22279,-11.06926 -5e-5,-15.29209 -2.11139,-2.1114 -4.87875,-3.1671 -7.64608,-3.16712 z m 4.50571,25.39817 c 0,0 0,0 0,0 0,0 0,0 0,0 z m 1e-5,0 z m 0,1e-5 c 10e-6,10e-6 2e-5,10e-6 2e-5,10e-6 0,0 -10e-6,-10e-6 -2e-5,-10e-6 z"
id="path140" />
</g>
</svg>

+ 72
- 63
src/app/CableWidget.cpp View File

@@ -15,6 +15,7 @@ namespace app {




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


@@ -22,6 +23,7 @@ struct CableWidget::Internal {
CableWidget::CableWidget() { CableWidget::CableWidget() {
internal = new Internal; internal = new Internal;
color = color::BLACK_TRANSPARENT; color = color::BLACK_TRANSPARENT;
internal->plugSvg = Svg::load(asset::system("res/ComponentLibrary/Plug.svg"));
internal->plugPortSvg = Svg::load(asset::system("res/ComponentLibrary/PlugPort.svg")); internal->plugPortSvg = Svg::load(asset::system("res/ComponentLibrary/PlugPort.svg"));
} }


@@ -124,91 +126,96 @@ void CableWidget::fromJson(json_t* rootJ) {
} }
} }


static void CableWidget_drawPlug(CableWidget* that, const widget::Widget::DrawArgs& args, math::Vec pos, NVGcolor color, bool top) {
static math::Vec getCableSlump(math::Vec pos1, math::Vec pos2) {
float dist = pos1.minus(pos2).norm();
math::Vec avg = pos1.plus(pos2).div(2);
// Lower average point as distance increases
avg.y += (1.0 - settings::cableTension) * (150.0 + 1.0 * dist);
return avg;
}

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


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


// Plug solid
nvgBeginPath(args.vg);
nvgCircle(args.vg, 0.0, 0.0, 9);
nvgFillColor(args.vg, color);
nvgFill(args.vg);
// Border
nvgStrokeWidth(args.vg, 1.0);
nvgStrokeColor(args.vg, colorOutline);
nvgStroke(args.vg);
// Plug
nvgSave(args.vg);
nvgTint(args.vg, color);
std::shared_ptr<Svg> plugSvg = that->internal->plugSvg;
math::Vec plugSize = plugSvg->getSize();
float angle = slump.minus(pos).arg() - 0.5f * M_PI;
nvgRotate(args.vg, angle);
nvgTranslate(args.vg, VEC_ARGS(plugSize.div(2).neg()));
plugSvg->draw(args.vg);
nvgRestore(args.vg);


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


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


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 colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5);
static void CableWidget_drawCable(CableWidget* that, const widget::Widget::DrawArgs& args, math::Vec pos1, math::Vec pos2, NVGcolor color, bool thick, float opacity) {
if (opacity <= 0.0)
return;


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

float dist = pos1.minus(pos2).norm();
math::Vec slump;
slump.y = (1.0 - tension) * (150.0 + 1.0 * dist);
math::Vec pos3 = pos1.plus(pos2).div(2).plus(slump);

// Adjust pos1 and pos2 to not draw over the plug
pos1 = pos1.plus(pos3.minus(pos1).normalize().mult(9));
pos2 = pos2.plus(pos3.minus(pos2).normalize().mult(9));

nvgLineJoin(args.vg, NVG_ROUND);

// Shadow
math::Vec pos4 = pos3.plus(slump.mult(0.08));
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
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
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, thickness - 2);
nvgStroke(args.vg);
float thickness = thick ? 10.0 : 6.0;


nvgRestore(args.vg);
}
// The endpoints are off-center
math::Vec slump = getCableSlump(pos1, pos2);
pos1 = pos1.plus(slump.minus(pos1).normalize().mult(13.0));
pos2 = pos2.plus(slump.minus(pos2).normalize().mult(13.0));

nvgSave(args.vg);
nvgAlpha(args.vg, std::pow(opacity, 1.5));

nvgLineCap(args.vg, NVG_ROUND);
// Avoids glitches when cable is bent
nvgLineJoin(args.vg, NVG_ROUND);

// Shadow
math::Vec shadowSlump = slump.plus(math::Vec(0, 30));
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, VEC_ARGS(pos1));
nvgQuadTo(args.vg, VEC_ARGS(shadowSlump), VEC_ARGS(pos2));
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.10);
nvgStrokeColor(args.vg, shadowColor);
nvgStrokeWidth(args.vg, thickness - 1.0);
nvgStroke(args.vg);

// Cable solid
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, VEC_ARGS(pos1));
nvgQuadTo(args.vg, VEC_ARGS(slump), VEC_ARGS(pos2));
// nvgStrokePaint(args.vg, nvgLinearGradient(args.vg, VEC_ARGS(pos1), VEC_ARGS(pos2), color::mult(color, 0.5), color));
nvgStrokeColor(args.vg, color::mult(color, 0.75));
nvgStrokeWidth(args.vg, thickness);
nvgStroke(args.vg);

nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, thickness - 1.0);
nvgStroke(args.vg);

nvgRestore(args.vg);
} }


void CableWidget::draw(const DrawArgs& args) { void CableWidget::draw(const DrawArgs& args) {
float opacity = settings::cableOpacity; float opacity = settings::cableOpacity;
float tension = settings::cableTension;
float thickness = 5;
bool thick = false;


if (isComplete()) { if (isComplete()) {
engine::Output* output = &cable->outputModule->outputs[cable->outputId]; engine::Output* output = &cable->outputModule->outputs[cable->outputId];
// Increase thickness if output port is polyphonic // Increase thickness if output port is polyphonic
if (output->channels > 1) { if (output->channels > 1) {
thickness = 9;
thick = true;
} }


// Draw opaque if mouse is hovering over a connected port // Draw opaque if mouse is hovering over a connected port
@@ -228,14 +235,17 @@ void CableWidget::draw(const DrawArgs& args) {


math::Vec outputPos = getOutputPos(); math::Vec outputPos = getOutputPos();
math::Vec inputPos = getInputPos(); math::Vec inputPos = getInputPos();
CableWidget_drawCable(this, args, outputPos, inputPos, color, thickness, tension, opacity);
CableWidget_drawCable(this, args, outputPos, inputPos, color, thick, 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();
math::Vec slump = getCableSlump(outputPos, inputPos);

// Draw output plug
bool outputTop = !isComplete() || APP->scene->rack->getTopCable(outputPort) == this; bool outputTop = !isComplete() || APP->scene->rack->getTopCable(outputPort) == this;
CableWidget_drawPlug(this, args, outputPos, color, outputTop);
CableWidget_drawPlug(this, args, outputPos, slump, color, outputTop);
if (outputTop && isComplete()) { if (outputTop && isComplete()) {
// Draw output plug light // Draw output plug light
nvgSave(args.vg); nvgSave(args.vg);
@@ -247,9 +257,8 @@ void CableWidget::drawPlugs(const DrawArgs& args) {
} }


// Draw input plug // Draw input plug
math::Vec inputPos = getInputPos();
bool inputTop = !isComplete() || APP->scene->rack->getTopCable(inputPort) == this; bool inputTop = !isComplete() || APP->scene->rack->getTopCable(inputPort) == this;
CableWidget_drawPlug(this, args, inputPos, color, inputTop);
CableWidget_drawPlug(this, args, inputPos, slump, color, inputTop);
if (inputTop && isComplete()) { if (inputTop && isComplete()) {
// Draw input plug light // Draw input plug light
nvgSave(args.vg); nvgSave(args.vg);


Loading…
Cancel
Save