| @@ -157,7 +157,8 @@ struct CircularShadow : TransparentWidget { | |||
| }; | |||
| struct Light : TransparentWidget { | |||
| NVGcolor color; | |||
| NVGcolor bgColor = nvgRGBf(0, 0, 0); | |||
| NVGcolor color = nvgRGBf(1, 1, 1); | |||
| void draw(NVGcontext *vg); | |||
| }; | |||
| @@ -321,6 +322,7 @@ struct PluginManagerWidget : Widget { | |||
| struct RackScene : Scene { | |||
| Toolbar *toolbar; | |||
| ScrollWidget *scrollWidget; | |||
| ZoomWidget *zoomWidget; | |||
| RackScene(); | |||
| void step(); | |||
| @@ -402,7 +402,7 @@ struct ColorValueLight : ValueLight { | |||
| void setValue(float v) { | |||
| v = sqrtBipolar(v); | |||
| 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) { | |||
| v = sqrtBipolar(v); | |||
| 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 | |||
| @@ -160,7 +160,7 @@ | |||
| x2="87.030029" | |||
| y2="73.994049" | |||
| gradientUnits="userSpaceOnUse" | |||
| gradientTransform="rotate(-90,83.154938,73.994048)" /> | |||
| gradientTransform="matrix(0,-0.93432349,0.93432349,0,14.020561,151.68766)" /> | |||
| </defs> | |||
| <sodipodi:namedview | |||
| id="base" | |||
| @@ -169,12 +169,12 @@ | |||
| borderopacity="1.0" | |||
| inkscape:pageopacity="0.0" | |||
| 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:current-layer="layer1" | |||
| showgrid="false" | |||
| inkscape:current-layer="g19440" | |||
| showgrid="true" | |||
| fit-margin-top="0" | |||
| fit-margin-left="0" | |||
| fit-margin-right="0" | |||
| @@ -186,7 +186,12 @@ | |||
| inkscape:window-maximized="0" | |||
| inkscape:snap-page="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 | |||
| id="metadata18402"> | |||
| <rdf:RDF> | |||
| @@ -195,7 +200,7 @@ | |||
| <dc:format>image/svg+xml</dc:format> | |||
| <dc:type | |||
| rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||
| <dc:title /> | |||
| <dc:title></dc:title> | |||
| </cc:Work> | |||
| </rdf:RDF> | |||
| </metadata> | |||
| @@ -217,12 +222,12 @@ | |||
| inkscape:connector-curvature="0" | |||
| id="path17974" | |||
| 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 | |||
| inkscape:connector-curvature="0" | |||
| id="path18024" | |||
| 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> | |||
| </svg> | |||
| @@ -160,7 +160,7 @@ | |||
| x2="87.030029" | |||
| y2="73.994049" | |||
| gradientUnits="userSpaceOnUse" | |||
| gradientTransform="rotate(-90,83.154938,73.994048)" /> | |||
| gradientTransform="matrix(0,-0.93432349,0.93432349,0,14.020561,151.68766)" /> | |||
| </defs> | |||
| <sodipodi:namedview | |||
| id="base" | |||
| @@ -169,12 +169,12 @@ | |||
| borderopacity="1.0" | |||
| inkscape:pageopacity="0.0" | |||
| 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:current-layer="layer1" | |||
| showgrid="false" | |||
| showgrid="true" | |||
| fit-margin-top="0" | |||
| fit-margin-left="0" | |||
| fit-margin-right="0" | |||
| @@ -186,7 +186,12 @@ | |||
| inkscape:window-maximized="0" | |||
| inkscape:snap-page="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 | |||
| id="metadata18402"> | |||
| <rdf:RDF> | |||
| @@ -217,12 +222,12 @@ | |||
| inkscape:connector-curvature="0" | |||
| id="path17974" | |||
| 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 | |||
| inkscape:connector-curvature="0" | |||
| id="path18024" | |||
| 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> | |||
| </svg> | |||
| @@ -5,8 +5,7 @@ namespace rack { | |||
| 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; | |||
| // Solid | |||
| @@ -17,7 +16,9 @@ void Light::draw(NVGcontext *vg) { | |||
| // Border | |||
| nvgStrokeWidth(vg, 1.0); | |||
| nvgStrokeColor(vg, nvgTransRGBAf(bgColor, 0.5)); | |||
| NVGcolor borderColor = bgColor; | |||
| borderColor.a *= 0.5; | |||
| nvgStrokeColor(vg, borderColor); | |||
| nvgStroke(vg); | |||
| // Inner glow | |||
| @@ -8,7 +8,7 @@ | |||
| namespace rack { | |||
| static std::string versionMessage = ""; | |||
| static std::string newVersion = ""; | |||
| static void checkVersion() { | |||
| json_t *resJ = requestJson(METHOD_GET, gApiHost + "/version", NULL); | |||
| @@ -18,7 +18,7 @@ static void checkVersion() { | |||
| if (versionJ) { | |||
| const char *version = json_string_value(versionJ); | |||
| 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); | |||
| @@ -29,14 +29,14 @@ static void checkVersion() { | |||
| RackScene::RackScene() { | |||
| 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); | |||
| @@ -52,19 +52,29 @@ RackScene::RackScene() { | |||
| } | |||
| void RackScene::step() { | |||
| // Resize owned descendants | |||
| toolbar->box.size.x = box.size.x; | |||
| 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(); | |||
| zoomWidget->box.size = gRackWidget->box.size.mult(zoomWidget->zoom); | |||
| // 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())) { | |||
| std::thread t(openBrowser, "https://vcvrack.com/"); | |||
| t.detach(); | |||
| guiClose(); | |||
| } | |||
| versionMessage = ""; | |||
| newVersion = ""; | |||
| } | |||
| } | |||
| @@ -304,12 +304,10 @@ void RackWidget::repositionModule(ModuleWidget *m) { | |||
| void RackWidget::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 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 | |||
| for (Widget *child : moduleContainer->children) { | |||
| @@ -26,7 +26,7 @@ void SVGSwitch::onChange() { | |||
| if (0 <= index && index < (int)frames.size()) | |||
| sw->svg = frames[index]; | |||
| dirty = true; | |||
| ParamWidget::onChange(); | |||
| Switch::onChange(); | |||
| } | |||
| @@ -172,7 +172,7 @@ void WireWidget::drawPlugs(NVGcontext *vg) { | |||
| Vec outputPos = getOutputPos(); | |||
| Vec inputPos = getInputPos(); | |||
| drawPlug(vg, outputPos, color); | |||
| drawPlug(vg, getInputPos(), color); | |||
| drawPlug(vg, inputPos, color); | |||
| // Draw plug light | |||
| /* | |||
| @@ -1,4 +1,5 @@ | |||
| #include <map> | |||
| #include <queue> | |||
| #include "gui.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) { | |||
| Vec mousePos = Vec(xpos, ypos).round(); | |||
| Vec mouseRel = mousePos.minus(gMousePos); | |||
| @@ -238,7 +261,7 @@ void guiInit() { | |||
| glfwSwapInterval(1); | |||
| glfwSetWindowSizeCallback(gWindow, windowSizeCallback); | |||
| glfwSetMouseButtonCallback(gWindow, mouseButtonCallback); | |||
| glfwSetMouseButtonCallback(gWindow, mouseButtonStickyCallback); | |||
| // glfwSetCursorPosCallback(gWindow, cursorPosCallback); | |||
| glfwSetCursorEnterCallback(gWindow, cursorEnterCallback); | |||
| glfwSetScrollCallback(gWindow, scrollCallback); | |||
| @@ -293,6 +316,7 @@ void guiRun() { | |||
| glfwGetCursorPos(gWindow, &xpos, &ypos); | |||
| cursorPosCallback(gWindow, xpos, ypos); | |||
| } | |||
| mouseButtonStickyPop(); | |||
| // Set window title | |||
| std::string title = gApplicationName + " " + gApplicationVersion; | |||
| @@ -15,6 +15,31 @@ static NVGcolor getNVGColor(uint32_t color) { | |||
| (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 */ | |||
| static float getLineCrossing(Vec p0, Vec p1, Vec p2, Vec p3) { | |||
| Vec b = p2.minus(p0); | |||
| @@ -121,30 +146,15 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||
| nvgFillColor(vg, color); | |||
| DEBUG_ONLY(printf(" fill color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);) | |||
| } 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: { | |||
| 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++) { | |||
| 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; | |||
| } | |||
| nvgFill(vg); | |||
| @@ -171,6 +181,9 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||
| } | |||
| nvgRestore(vg); | |||
| // if (std::string(shape->id) == "rect19347") | |||
| // exit(0); | |||
| } | |||
| DEBUG_ONLY(printf("\n");) | |||
| @@ -8,13 +8,13 @@ namespace rack { | |||
| void ScrollBar::draw(NVGcontext *vg) { | |||
| ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent); | |||
| 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); | |||
| bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | |||
| } | |||