@@ -157,7 +157,8 @@ struct CircularShadow : TransparentWidget { | |||||
}; | }; | ||||
struct Light : TransparentWidget { | struct Light : TransparentWidget { | ||||
NVGcolor color; | |||||
NVGcolor bgColor = nvgRGBf(0, 0, 0); | |||||
NVGcolor color = nvgRGBf(1, 1, 1); | |||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -321,6 +322,7 @@ struct PluginManagerWidget : Widget { | |||||
struct RackScene : Scene { | struct RackScene : Scene { | ||||
Toolbar *toolbar; | Toolbar *toolbar; | ||||
ScrollWidget *scrollWidget; | ScrollWidget *scrollWidget; | ||||
ZoomWidget *zoomWidget; | |||||
RackScene(); | RackScene(); | ||||
void step(); | void step(); | ||||
@@ -402,7 +402,7 @@ struct ColorValueLight : ValueLight { | |||||
void setValue(float v) { | void setValue(float v) { | ||||
v = sqrtBipolar(v); | v = sqrtBipolar(v); | ||||
color = baseColor; | color = baseColor; | ||||
color.a = clampf(v, 0.0, 1.0); | |||||
color.a = clampf(v * baseColor.a, 0.0, 1.0); | |||||
} | } | ||||
}; | }; | ||||
@@ -430,7 +430,7 @@ struct PolarityLight : ValueLight { | |||||
void setValue(float v) { | void setValue(float v) { | ||||
v = sqrtBipolar(v); | v = sqrtBipolar(v); | ||||
color = (v >= 0.0) ? posColor : negColor; | color = (v >= 0.0) ? posColor : negColor; | ||||
color.a = clampf(fabsf(v), 0.0, 1.0); | |||||
color.a = clampf(fabsf(v) * color.a, 0.0, 1.0); | |||||
} | } | ||||
}; | }; | ||||
@@ -548,6 +548,15 @@ struct BefacoPush : SVGSwitch, MomentarySwitch { | |||||
} | } | ||||
}; | }; | ||||
struct PB61303 : SVGSwitch, MomentarySwitch { | |||||
PB61303() { | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303_0.svg"))); | |||||
addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303_1.svg"))); | |||||
sw->wrap(); | |||||
box.size = sw->box.size; | |||||
} | |||||
}; | |||||
//////////////////// | //////////////////// | ||||
// Misc | // Misc | ||||
@@ -160,7 +160,7 @@ | |||||
x2="87.030029" | x2="87.030029" | ||||
y2="73.994049" | y2="73.994049" | ||||
gradientUnits="userSpaceOnUse" | gradientUnits="userSpaceOnUse" | ||||
gradientTransform="rotate(-90,83.154938,73.994048)" /> | |||||
gradientTransform="matrix(0,-0.93432349,0.93432349,0,14.020561,151.68766)" /> | |||||
</defs> | </defs> | ||||
<sodipodi:namedview | <sodipodi:namedview | ||||
id="base" | id="base" | ||||
@@ -169,12 +169,12 @@ | |||||
borderopacity="1.0" | borderopacity="1.0" | ||||
inkscape:pageopacity="0.0" | inkscape:pageopacity="0.0" | ||||
inkscape:pageshadow="2" | inkscape:pageshadow="2" | ||||
inkscape:zoom="7.9195959" | |||||
inkscape:cx="22.964109" | |||||
inkscape:cy="8.9651844" | |||||
inkscape:zoom="22.4" | |||||
inkscape:cx="22.801127" | |||||
inkscape:cy="13.743925" | |||||
inkscape:document-units="mm" | inkscape:document-units="mm" | ||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
inkscape:current-layer="g19440" | |||||
showgrid="true" | |||||
fit-margin-top="0" | fit-margin-top="0" | ||||
fit-margin-left="0" | fit-margin-left="0" | ||||
fit-margin-right="0" | fit-margin-right="0" | ||||
@@ -186,7 +186,12 @@ | |||||
inkscape:window-maximized="0" | inkscape:window-maximized="0" | ||||
inkscape:snap-page="true" | inkscape:snap-page="true" | ||||
inkscape:snap-bbox="true" | inkscape:snap-bbox="true" | ||||
inkscape:bbox-nodes="true" /> | |||||
inkscape:bbox-nodes="true" | |||||
inkscape:object-nodes="false"> | |||||
<inkscape:grid | |||||
type="xygrid" | |||||
id="grid20375" /> | |||||
</sodipodi:namedview> | |||||
<metadata | <metadata | ||||
id="metadata18402"> | id="metadata18402"> | ||||
<rdf:RDF> | <rdf:RDF> | ||||
@@ -195,7 +200,7 @@ | |||||
<dc:format>image/svg+xml</dc:format> | <dc:format>image/svg+xml</dc:format> | ||||
<dc:type | <dc:type | ||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
<dc:title /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | </cc:Work> | ||||
</rdf:RDF> | </rdf:RDF> | ||||
</metadata> | </metadata> | ||||
@@ -217,12 +222,12 @@ | |||||
inkscape:connector-curvature="0" | inkscape:connector-curvature="0" | ||||
id="path17974" | id="path17974" | ||||
style="fill:#6b6969;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45976272" | style="fill:#6b6969;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45976272" | ||||
d="m 87.654936,73.994048 c 0,2.484967 -2.014361,4.49968 -4.500033,4.49968 -2.485672,0 -4.500033,-2.014713 -4.500033,-4.49968 0,-2.484967 2.014361,-4.49968 4.500033,-4.49968 2.485672,0 4.500033,2.014713 4.500033,4.49968" /> | |||||
d="m 87.465003,73.994048 c 0,2.380367 -1.929341,4.310275 -4.3101,4.310275 -2.380759,0 -4.310099,-1.929908 -4.310099,-4.310275 0,-2.380367 1.92934,-4.310275 4.310099,-4.310275 2.380759,0 4.3101,1.929908 4.3101,4.310275" /> | |||||
<path | <path | ||||
inkscape:connector-curvature="0" | inkscape:connector-curvature="0" | ||||
id="path18024" | id="path18024" | ||||
style="fill:url(#linearGradient19435);fill-opacity:1;stroke:none;stroke-width:0.45976272" | style="fill:url(#linearGradient19435);fill-opacity:1;stroke:none;stroke-width:0.45976272" | ||||
d="m 79.280028,73.994224 c 0,2.140303 1.735314,3.874911 3.87491,3.874911 2.139597,0 3.874911,-1.734608 3.874911,-3.874911 0,-2.140656 -1.735314,-3.875264 -3.874911,-3.875264 -2.139596,0 -3.87491,1.734608 -3.87491,3.875264 m 0.176389,0 c 0,-2.039761 1.659114,-3.698875 3.698521,-3.698875 2.039408,0 3.698522,1.659114 3.698522,3.698875 0,2.039408 -1.659114,3.698522 -3.698522,3.698522 -2.039407,0 -3.698521,-1.659114 -3.698521,-3.698522" /> | |||||
d="m 79.534519,73.994213 c 0,1.999735 1.621344,3.62042 3.620419,3.62042 1.999076,0 3.620421,-1.620685 3.620421,-3.62042 0,-2.000066 -1.621345,-3.620751 -3.620421,-3.620751 -1.999075,0 -3.620419,1.620685 -3.620419,3.620751 m 0.164804,0 c 0,-1.905797 1.550149,-3.455946 3.455615,-3.455946 1.905467,0 3.455616,1.550149 3.455616,3.455946 0,1.905466 -1.550149,3.455615 -3.455616,3.455615 -1.905466,0 -3.455615,-1.550149 -3.455615,-3.455615" /> | |||||
</g> | </g> | ||||
</g> | </g> | ||||
</svg> | </svg> |
@@ -160,7 +160,7 @@ | |||||
x2="87.030029" | x2="87.030029" | ||||
y2="73.994049" | y2="73.994049" | ||||
gradientUnits="userSpaceOnUse" | gradientUnits="userSpaceOnUse" | ||||
gradientTransform="rotate(-90,83.154938,73.994048)" /> | |||||
gradientTransform="matrix(0,-0.93432349,0.93432349,0,14.020561,151.68766)" /> | |||||
</defs> | </defs> | ||||
<sodipodi:namedview | <sodipodi:namedview | ||||
id="base" | id="base" | ||||
@@ -169,12 +169,12 @@ | |||||
borderopacity="1.0" | borderopacity="1.0" | ||||
inkscape:pageopacity="0.0" | inkscape:pageopacity="0.0" | ||||
inkscape:pageshadow="2" | inkscape:pageshadow="2" | ||||
inkscape:zoom="7.9195959" | |||||
inkscape:cx="22.964109" | |||||
inkscape:cy="8.9651844" | |||||
inkscape:zoom="22.4" | |||||
inkscape:cx="22.801127" | |||||
inkscape:cy="13.743925" | |||||
inkscape:document-units="mm" | inkscape:document-units="mm" | ||||
inkscape:current-layer="layer1" | inkscape:current-layer="layer1" | ||||
showgrid="false" | |||||
showgrid="true" | |||||
fit-margin-top="0" | fit-margin-top="0" | ||||
fit-margin-left="0" | fit-margin-left="0" | ||||
fit-margin-right="0" | fit-margin-right="0" | ||||
@@ -186,7 +186,12 @@ | |||||
inkscape:window-maximized="0" | inkscape:window-maximized="0" | ||||
inkscape:snap-page="true" | inkscape:snap-page="true" | ||||
inkscape:snap-bbox="true" | inkscape:snap-bbox="true" | ||||
inkscape:bbox-nodes="true" /> | |||||
inkscape:bbox-nodes="true" | |||||
inkscape:object-nodes="false"> | |||||
<inkscape:grid | |||||
type="xygrid" | |||||
id="grid20375" /> | |||||
</sodipodi:namedview> | |||||
<metadata | <metadata | ||||
id="metadata18402"> | id="metadata18402"> | ||||
<rdf:RDF> | <rdf:RDF> | ||||
@@ -217,12 +222,12 @@ | |||||
inkscape:connector-curvature="0" | inkscape:connector-curvature="0" | ||||
id="path17974" | id="path17974" | ||||
style="fill:#6b6969;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45976272" | style="fill:#6b6969;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45976272" | ||||
d="m 87.654936,73.994048 c 0,2.484967 -2.014361,4.49968 -4.500033,4.49968 -2.485672,0 -4.500033,-2.014713 -4.500033,-4.49968 0,-2.484967 2.014361,-4.49968 4.500033,-4.49968 2.485672,0 4.500033,2.014713 4.500033,4.49968" /> | |||||
d="m 87.465003,73.994048 c 0,2.380367 -1.929341,4.310275 -4.3101,4.310275 -2.380759,0 -4.310099,-1.929908 -4.310099,-4.310275 0,-2.380367 1.92934,-4.310275 4.310099,-4.310275 2.380759,0 4.3101,1.929908 4.3101,4.310275" /> | |||||
<path | <path | ||||
inkscape:connector-curvature="0" | inkscape:connector-curvature="0" | ||||
id="path18024" | id="path18024" | ||||
style="fill:url(#linearGradient19435);fill-opacity:1;stroke:none;stroke-width:0.45976272" | style="fill:url(#linearGradient19435);fill-opacity:1;stroke:none;stroke-width:0.45976272" | ||||
d="m 79.280028,73.994224 c 0,2.140303 1.735314,3.874911 3.87491,3.874911 2.139597,0 3.874911,-1.734608 3.874911,-3.874911 0,-2.140656 -1.735314,-3.875264 -3.874911,-3.875264 -2.139596,0 -3.87491,1.734608 -3.87491,3.875264 m 0.176389,0 c 0,-2.039761 1.659114,-3.698875 3.698521,-3.698875 2.039408,0 3.698522,1.659114 3.698522,3.698875 0,2.039408 -1.659114,3.698522 -3.698522,3.698522 -2.039407,0 -3.698521,-1.659114 -3.698521,-3.698522" /> | |||||
d="m 79.534519,73.994213 c 0,1.999735 1.621344,3.62042 3.620419,3.62042 1.999076,0 3.620421,-1.620685 3.620421,-3.62042 0,-2.000066 -1.621345,-3.620751 -3.620421,-3.620751 -1.999075,0 -3.620419,1.620685 -3.620419,3.620751 m 0.164804,0 c 0,-1.905797 1.550149,-3.455946 3.455615,-3.455946 1.905467,0 3.455616,1.550149 3.455616,3.455946 0,1.905466 -1.550149,3.455615 -3.455616,3.455615 -1.905466,0 -3.455615,-1.550149 -3.455615,-3.455615" /> | |||||
</g> | </g> | ||||
</g> | </g> | ||||
</svg> | </svg> |
@@ -5,8 +5,7 @@ namespace rack { | |||||
void Light::draw(NVGcontext *vg) { | void Light::draw(NVGcontext *vg) { | ||||
NVGcolor bgColor = nvgRGBf(0.0, 0.0, 0.0); | |||||
float radius = roundf(box.size.x / 2.0); | |||||
float radius = box.size.x / 2.0; | |||||
float oradius = radius + 30.0; | float oradius = radius + 30.0; | ||||
// Solid | // Solid | ||||
@@ -17,7 +16,9 @@ void Light::draw(NVGcontext *vg) { | |||||
// Border | // Border | ||||
nvgStrokeWidth(vg, 1.0); | nvgStrokeWidth(vg, 1.0); | ||||
nvgStrokeColor(vg, nvgTransRGBAf(bgColor, 0.5)); | |||||
NVGcolor borderColor = bgColor; | |||||
borderColor.a *= 0.5; | |||||
nvgStrokeColor(vg, borderColor); | |||||
nvgStroke(vg); | nvgStroke(vg); | ||||
// Inner glow | // Inner glow | ||||
@@ -8,7 +8,7 @@ | |||||
namespace rack { | namespace rack { | ||||
static std::string versionMessage = ""; | |||||
static std::string newVersion = ""; | |||||
static void checkVersion() { | static void checkVersion() { | ||||
json_t *resJ = requestJson(METHOD_GET, gApiHost + "/version", NULL); | json_t *resJ = requestJson(METHOD_GET, gApiHost + "/version", NULL); | ||||
@@ -18,7 +18,7 @@ static void checkVersion() { | |||||
if (versionJ) { | if (versionJ) { | ||||
const char *version = json_string_value(versionJ); | const char *version = json_string_value(versionJ); | ||||
if (version && version != gApplicationVersion) { | if (version && version != gApplicationVersion) { | ||||
versionMessage = stringf("Rack %s is available.\n\nYou have Rack %s.\n\nWould you like to download the new version on the website?", version, gApplicationVersion.c_str()); | |||||
newVersion = version; | |||||
} | } | ||||
} | } | ||||
json_decref(resJ); | json_decref(resJ); | ||||
@@ -29,14 +29,14 @@ static void checkVersion() { | |||||
RackScene::RackScene() { | RackScene::RackScene() { | ||||
scrollWidget = new ScrollWidget(); | scrollWidget = new ScrollWidget(); | ||||
{ | { | ||||
// ZoomWidget *zoomWidget = new ZoomWidget(); | |||||
// zoomWidget->zoom = 0.8; | |||||
// scrollWidget->container->addChild(zoomWidget); | |||||
assert(!gRackWidget); | |||||
gRackWidget = new RackWidget(); | |||||
scrollWidget->container->addChild(gRackWidget); | |||||
// zoomWidget->addChild(gRackWidget); | |||||
zoomWidget = new ZoomWidget(); | |||||
zoomWidget->zoom = 1.0; | |||||
{ | |||||
assert(!gRackWidget); | |||||
gRackWidget = new RackWidget(); | |||||
zoomWidget->addChild(gRackWidget); | |||||
} | |||||
scrollWidget->container->addChild(zoomWidget); | |||||
} | } | ||||
addChild(scrollWidget); | addChild(scrollWidget); | ||||
@@ -52,19 +52,29 @@ RackScene::RackScene() { | |||||
} | } | ||||
void RackScene::step() { | void RackScene::step() { | ||||
// Resize owned descendants | |||||
toolbar->box.size.x = box.size.x; | toolbar->box.size.x = box.size.x; | ||||
scrollWidget->box.size = box.size.minus(scrollWidget->box.pos); | scrollWidget->box.size = box.size.minus(scrollWidget->box.pos); | ||||
// Resize to be a bit larger than the ScrollWidget viewport | |||||
gRackWidget->box.size = scrollWidget->box.size | |||||
.minus(scrollWidget->container->box.pos) | |||||
.plus(Vec(500, 500)) | |||||
.div(zoomWidget->zoom); | |||||
Scene::step(); | Scene::step(); | ||||
zoomWidget->box.size = gRackWidget->box.size.mult(zoomWidget->zoom); | |||||
// Version popup message | // Version popup message | ||||
if (!versionMessage.empty()) { | |||||
if (!newVersion.empty()) { | |||||
std::string versionMessage = stringf("Rack %s is available.\n\nYou have Rack %s.\n\nWould you like to download the new version on the website?", newVersion, gApplicationVersion.c_str()); | |||||
if (osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, versionMessage.c_str())) { | if (osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, versionMessage.c_str())) { | ||||
std::thread t(openBrowser, "https://vcvrack.com/"); | std::thread t(openBrowser, "https://vcvrack.com/"); | ||||
t.detach(); | t.detach(); | ||||
guiClose(); | guiClose(); | ||||
} | } | ||||
versionMessage = ""; | |||||
newVersion = ""; | |||||
} | } | ||||
} | } | ||||
@@ -304,12 +304,10 @@ void RackWidget::repositionModule(ModuleWidget *m) { | |||||
void RackWidget::step() { | void RackWidget::step() { | ||||
rails->step(); | rails->step(); | ||||
// Resize to be a bit larger than the ScrollWidget viewport | |||||
assert(parent); | |||||
assert(parent->parent); | |||||
// Expand size to fit modules | |||||
Vec moduleSize = moduleContainer->getChildrenBoundingBox().getBottomRight(); | Vec moduleSize = moduleContainer->getChildrenBoundingBox().getBottomRight(); | ||||
Vec viewportSize = parent->parent->box.size.minus(parent->box.pos); | |||||
box.size = moduleSize.max(viewportSize).plus(Vec(500, 500)); | |||||
// We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded. | |||||
box.size = box.size.max(moduleSize); | |||||
// Reposition modules | // Reposition modules | ||||
for (Widget *child : moduleContainer->children) { | for (Widget *child : moduleContainer->children) { | ||||
@@ -26,7 +26,7 @@ void SVGSwitch::onChange() { | |||||
if (0 <= index && index < (int)frames.size()) | if (0 <= index && index < (int)frames.size()) | ||||
sw->svg = frames[index]; | sw->svg = frames[index]; | ||||
dirty = true; | dirty = true; | ||||
ParamWidget::onChange(); | |||||
Switch::onChange(); | |||||
} | } | ||||
@@ -172,7 +172,7 @@ void WireWidget::drawPlugs(NVGcontext *vg) { | |||||
Vec outputPos = getOutputPos(); | Vec outputPos = getOutputPos(); | ||||
Vec inputPos = getInputPos(); | Vec inputPos = getInputPos(); | ||||
drawPlug(vg, outputPos, color); | drawPlug(vg, outputPos, color); | ||||
drawPlug(vg, getInputPos(), color); | |||||
drawPlug(vg, inputPos, color); | |||||
// Draw plug light | // Draw plug light | ||||
/* | /* | ||||
@@ -1,4 +1,5 @@ | |||||
#include <map> | #include <map> | ||||
#include <queue> | |||||
#include "gui.hpp" | #include "gui.hpp" | ||||
#include "app.hpp" | #include "app.hpp" | ||||
@@ -87,6 +88,28 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
} | } | ||||
} | } | ||||
struct MouseButtonArguments { | |||||
GLFWwindow *window; | |||||
int button; | |||||
int action; | |||||
int mods; | |||||
}; | |||||
static std::queue<MouseButtonArguments> mouseButtonQueue; | |||||
void mouseButtonStickyPop() { | |||||
if (!mouseButtonQueue.empty()) { | |||||
MouseButtonArguments args = mouseButtonQueue.front(); | |||||
mouseButtonQueue.pop(); | |||||
mouseButtonCallback(args.window, args.button, args.action, args.mods); | |||||
} | |||||
} | |||||
void mouseButtonStickyCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
// Defer multiple clicks per frame to future frames | |||||
MouseButtonArguments args = {window, button, action, mods}; | |||||
mouseButtonQueue.push(args); | |||||
} | |||||
void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | ||||
Vec mousePos = Vec(xpos, ypos).round(); | Vec mousePos = Vec(xpos, ypos).round(); | ||||
Vec mouseRel = mousePos.minus(gMousePos); | Vec mouseRel = mousePos.minus(gMousePos); | ||||
@@ -238,7 +261,7 @@ void guiInit() { | |||||
glfwSwapInterval(1); | glfwSwapInterval(1); | ||||
glfwSetWindowSizeCallback(gWindow, windowSizeCallback); | glfwSetWindowSizeCallback(gWindow, windowSizeCallback); | ||||
glfwSetMouseButtonCallback(gWindow, mouseButtonCallback); | |||||
glfwSetMouseButtonCallback(gWindow, mouseButtonStickyCallback); | |||||
// glfwSetCursorPosCallback(gWindow, cursorPosCallback); | // glfwSetCursorPosCallback(gWindow, cursorPosCallback); | ||||
glfwSetCursorEnterCallback(gWindow, cursorEnterCallback); | glfwSetCursorEnterCallback(gWindow, cursorEnterCallback); | ||||
glfwSetScrollCallback(gWindow, scrollCallback); | glfwSetScrollCallback(gWindow, scrollCallback); | ||||
@@ -293,6 +316,7 @@ void guiRun() { | |||||
glfwGetCursorPos(gWindow, &xpos, &ypos); | glfwGetCursorPos(gWindow, &xpos, &ypos); | ||||
cursorPosCallback(gWindow, xpos, ypos); | cursorPosCallback(gWindow, xpos, ypos); | ||||
} | } | ||||
mouseButtonStickyPop(); | |||||
// Set window title | // Set window title | ||||
std::string title = gApplicationName + " " + gApplicationVersion; | std::string title = gApplicationName + " " + gApplicationVersion; | ||||
@@ -15,6 +15,31 @@ static NVGcolor getNVGColor(uint32_t color) { | |||||
(color >> 24) & 0xff); | (color >> 24) & 0xff); | ||||
} | } | ||||
static NVGpaint getPaint(NVGcontext *vg, NSVGpaint *p) { | |||||
assert(p->type == NSVG_PAINT_LINEAR_GRADIENT || p->type == NSVG_PAINT_RADIAL_GRADIENT); | |||||
NSVGgradient *g = p->gradient; | |||||
assert(g->nstops >= 1); | |||||
NVGcolor icol = getNVGColor(g->stops[0].color); | |||||
NVGcolor ocol = getNVGColor(g->stops[g->nstops - 1].color); | |||||
float inverse[6]; | |||||
nvgTransformInverse(inverse, g->xform); | |||||
DEBUG_ONLY(printf(" inverse: %f %f %f %f %f %f\n", inverse[0], inverse[1], inverse[2], inverse[3], inverse[4], inverse[5]);) | |||||
Vec s, e; | |||||
DEBUG_ONLY(printf(" sx: %f sy: %f ex: %f ey: %f\n", s.x, s.y, e.x, e.y);) | |||||
// Is it always the case that the gradient should be transformed from (0, 0) to (0, 1)? | |||||
nvgTransformPoint(&s.x, &s.y, inverse, 0, 0); | |||||
nvgTransformPoint(&e.x, &e.y, inverse, 0, 1); | |||||
DEBUG_ONLY(printf(" sx: %f sy: %f ex: %f ey: %f\n", s.x, s.y, e.x, e.y);) | |||||
NVGpaint paint; | |||||
if (p->type == NSVG_PAINT_LINEAR_GRADIENT) | |||||
paint = nvgLinearGradient(vg, s.x, s.y, e.x, e.y, icol, ocol); | |||||
else | |||||
paint = nvgRadialGradient(vg, s.x, s.y, 0.0, 160, icol, ocol); | |||||
return paint; | |||||
} | |||||
/** Returns the parameterized value of the line p2--p3 where it intersects with p0--p1 */ | /** Returns the parameterized value of the line p2--p3 where it intersects with p0--p1 */ | ||||
static float getLineCrossing(Vec p0, Vec p1, Vec p2, Vec p3) { | static float getLineCrossing(Vec p0, Vec p1, Vec p2, Vec p3) { | ||||
Vec b = p2.minus(p0); | Vec b = p2.minus(p0); | ||||
@@ -121,30 +146,15 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
DEBUG_ONLY(printf(" fill color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);) | DEBUG_ONLY(printf(" fill color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);) | ||||
} break; | } break; | ||||
case NSVG_PAINT_LINEAR_GRADIENT: { | |||||
NSVGgradient *g = shape->fill.gradient; | |||||
(void)g; | |||||
DEBUG_ONLY(printf(" linear gradient: %f\t%f\n", g->fx, g->fy);) | |||||
} break; | |||||
case NSVG_PAINT_LINEAR_GRADIENT: | |||||
case NSVG_PAINT_RADIAL_GRADIENT: { | case NSVG_PAINT_RADIAL_GRADIENT: { | ||||
NSVGgradient *g = shape->fill.gradient; | NSVGgradient *g = shape->fill.gradient; | ||||
DEBUG_ONLY(printf(" radial gradient: %f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n", g->fx, g->fy, g->xform[0], g->xform[1], g->xform[2], g->xform[3], g->xform[4], g->xform[5]);) | |||||
(void)g; | |||||
DEBUG_ONLY(printf(" gradient: type: %s xform: %f %f %f %f %f %f spread: %d fx: %f fy: %f nstops: %d\n", (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT ? "linear" : "radial"), g->xform[0], g->xform[1], g->xform[2], g->xform[3], g->xform[4], g->xform[5], g->spread, g->fx, g->fy, g->nstops);) | |||||
for (int i = 0; i < g->nstops; i++) { | for (int i = 0; i < g->nstops; i++) { | ||||
DEBUG_ONLY(printf(" stop: #%08x\t%f\n", g->stops[i].color, g->stops[i].offset);) | DEBUG_ONLY(printf(" stop: #%08x\t%f\n", g->stops[i].color, g->stops[i].offset);) | ||||
} | } | ||||
assert(g->nstops >= 1); | |||||
NVGcolor color0 = getNVGColor(g->stops[0].color); | |||||
NVGcolor color1 = getNVGColor(g->stops[g->nstops - 1].color); | |||||
float inverse[6]; | |||||
// Rect shapeBox = Rect::fromMinMax(Vec(shape->bounds[0], shape->bounds[1]), Vec(shape->bounds[2], shape->bounds[3])); | |||||
nvgTransformInverse(inverse, g->xform); | |||||
Vec c; | |||||
nvgTransformPoint(&c.x, &c.y, inverse, 5, 5); | |||||
printf("%f %f\n", c.x, c.y); | |||||
NVGpaint paint = nvgRadialGradient(vg, c.x, c.y, 0.0, 160, color0, color1); | |||||
nvgFillPaint(vg, paint); | |||||
nvgFillPaint(vg, getPaint(vg, &shape->fill)); | |||||
} break; | } break; | ||||
} | } | ||||
nvgFill(vg); | nvgFill(vg); | ||||
@@ -171,6 +181,9 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
} | } | ||||
nvgRestore(vg); | nvgRestore(vg); | ||||
// if (std::string(shape->id) == "rect19347") | |||||
// exit(0); | |||||
} | } | ||||
DEBUG_ONLY(printf("\n");) | DEBUG_ONLY(printf("\n");) | ||||
@@ -8,13 +8,13 @@ namespace rack { | |||||
void ScrollBar::draw(NVGcontext *vg) { | void ScrollBar::draw(NVGcontext *vg) { | ||||
ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent); | ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent); | ||||
assert(scrollWidget); | assert(scrollWidget); | ||||
Vec containerCorner = scrollWidget->container->getChildrenBoundingBox().getBottomRight(); | |||||
Vec viewportCorner = scrollWidget->container->getChildrenBoundingBox().getBottomRight(); | |||||
float containerSize = (orientation == HORIZONTAL) ? containerCorner.x : containerCorner.y; | |||||
float boxSize = (orientation == HORIZONTAL) ? box.size.x : box.size.y; | |||||
float offset = (orientation == HORIZONTAL) ? scrollWidget->offset.x : scrollWidget->offset.y; | |||||
offset = offset / (containerSize - boxSize); | |||||
float size = boxSize / containerSize; | |||||
float viewportSize = (orientation == HORIZONTAL) ? viewportCorner.x : viewportCorner.y; | |||||
float containerSize = (orientation == HORIZONTAL) ? scrollWidget->box.size.x : scrollWidget->box.size.y; | |||||
float viewportOffset = (orientation == HORIZONTAL) ? scrollWidget->offset.x : scrollWidget->offset.y; | |||||
float offset = viewportOffset / (viewportSize - containerSize); | |||||
float size = containerSize / viewportSize; | |||||
size = clampf(size, 0.0, 1.0); | size = clampf(size, 0.0, 1.0); | ||||
bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | ||||
} | } | ||||