SvgSlider: Rect instead of image?

Hi,

is there a way to set, for the handle of my custom SvgSlider, to place a nv Rect instead of image? So, instead of:

setHandleSvg(APP->window->loadSvg(path));

set the data from this?

nvgBeginPath(args.vg);
nvgFillColor(args.vg, customColor);
nvgRect(args.vg, 0.0f, 0.0f, width, height);
nvgFill(args.vg);
nvgClosePath(args.vg);

Is it possible? This because I would like to have different SvgSlider that will vary only the handle background color, without create N .svg images.

Thanks

Greetings!

First I would recommend examining the following files in the Rack source code:

SliderKnob.hpp
SvgSlider.hpp
SvgSlider.cpp

Then I’d create 3 new structs for (1) the slider widget itself (lets call it q8fuelSlider), (2) the background (q8fuelSliderBackground), and (3) handle (q8fuelSliderHandle: the part you click and drag with the mouse)

namespace rack {
namespace app {

struct q8fuelSliderBackground::OpaqueWidget {
  NVGcolor customColor;
  q8fuelSliderBackground();
  void draw(const DrawArgs& args) override {
   //your draw code for the background
  }
};

//then another struct for the custom slider handle called q8fuelSliderHandle

struct q8fuelSlider : SliderKnob {
	widget::FramebufferWidget* fb;

        //you dont want an SvgWidget, you want your new custom background widget
        //widget::SvgWidget* background;
        q8fuelSliderBackground* background;

        //you dont want an SvgWidget, you want your custom handle widget
	    //widget::SvgWidget* handle;
        q8fuelSliderHandle* handle;


	/** Intermediate positions will be interpolated between these positions */
	math::Vec minHandlePos, maxHandlePos;
...

You’ll probably want to copy most of the code in SvgSlider.cpp so that your slider behaves the same way.

Hopefully this helps you to get started! Good luck!

1 Like

Yes, that’s somethings I don’t like to do in general. If in Rack 2.0 some “native” widgets code change internally, I need to migrate each changes for my copied class.

Instead, if I keep the max I can out of the already code, to extend it is better to maintain.

All I need here is a sort of nanoVG path to NSVGimage (or easily, NSVGshape). Hope there is somethings, else I will follow your suggestions.

Anyone?

Take a look at nanosvg.h, an NSVGimage only uses cubic bezier curves. Your options are:

  • Build your widget from curves, creating NVGpaths and NVGshapes by hand basically.

  • Modify an NVGimage’s shapes’ fill and stroke after parsing it from an svg file.

  • Go with the suggestion if you want to use nvg drawing commands as in your example.

I understand this desire, but in the case of the component you are trying to create the code you’d be copying from SvgSlider is quite trivial. Your custom draw code would be more lines than what you’d have to copy.

Another option: according to @synthi in this thread: Buttons, SVG and layers it is possible to interact with individual elements of an SVG. I’ve never tried this so I can’t be of any help, but perhaps you could create some “template” SVGs, and then change their color in your component’s step() method as Antonio suggests. This way your component could inherit from SvgSlider.

That wouldn’t be a bad idea. In fact, the only “property” I need to change is just the fill color - i.e. fill="#231f20" attribute.

Editing the NSVGshape.NSVGpaint should make the tricks… not sure about the color :slight_smile: Its an integer?

unsigned int color;

?

an rgb color with alpha channel, like #FF0000FF?

Yes, but which integer should I place? :slight_smile:

Tried a “random” number, such as handle->svg->handle->shapes->fill.color = 12; but the backgroud vanish eheh.

Not sure which value to set there :frowning:

Maybe bitwise?

from nanovg.h

// Colors in NanoVG are stored as unsigned ints in ABGR format.

1 Like

I think I got it :slight_smile:

auto r = 255 & 0xFF;
auto g = 0 & 0xFF;
auto b = 0 & 0xFF;
auto a = 255 & 0xFF;

int abgr = (a << 24) + (b << 16) + (g << 8) + (r);

Seems to works fancy :smiley:

you can also use hex notation like

unsigned int abgr = 0xff0000ff;
1 Like

Nice :slight_smile: With one line of code, I’ve fixed the problem. Thanks magic guys!!!

It seems that handle is “cached”, so change one, change for every controls.

So, if for example I want 3 red and 2 yellow? Would you set it every time at step()? For each param?

2 Likes

This is not part of the stable/public API.

I might start locking this stuff down with opaque pointers in Rack v2.

What’s the best solution in this case? Duplicate your code of SvgSlider (adapting it) without inherit from it?