Resizing SVGKnobs without adding new SVGs

I’m new to both VCV Rack plugin development and programming in C++. I’d like to quickly resize my knobs when using addparam(createParamCentered<KnobStruct>(...)), though I haven’t found any way that works. I’d rather not have to add different SVGs for every size I’d like to use and then keep defining structs to load them in. Please give me any ideas or workarounds.

You basically have a couple of options

  1. Add SVGs and make a little throwaway class for each size you want.
  2. Dont’ use SVGs at all; paint in a frame buffer using code; make the size a template argument
  3. There’s probably a third option where you use a TransformWidget containing a knob and set it up but that’s not a single template argument.

Surge uses a mix of 1 and 2 (we have 30 odd svgs for our knobs pointers and skins and draw the rings). Airwindows and BaconPlugs uses the second. I have not used the third but i bet it could work with some poking.


Another option:

I implemented a simple svg theming library that manipulates the in-memory representation of the SVG: svg_theme: Lean in-memory SVG theming for VCV Rack plugins.. This currently manipulates only colors and gradients, and doesn’t do anything with scaling or coordinates.

You could use the same techniques used in my library to take a custom SVG with a named top-level 1:1 scaling transform and change the dimensions and modify the transform in-place. I think that’s do-able, and would be a great contribution to the svg_theme library.

The drawback of scaling such as using a TransformWidget is that it can end up not looking very good in some zoom levels or in the browser. Highest quality will be with an SVG designed for the size, or custom-draw widget.

But… the methods the other Paul mentions are easier to implement.

In the end, you’ll probably end up with clearer and more consistent module designs by having a limited selection of knob sizes (just like there are not arbitrarily sized parts for physical modules, unless you 3D-print your own).

1 Like

Before I say anything else, this sentence makes me think I’ve likely XY-problemed myself. I need to figure out a good overall design first and then stick to it. I already have some template panels which I can just resize and decorate in Inkscape, but I often make fundamental design changes, and I don’t want to go back and take so long editing things.

Maybe I can get the best of both worlds by just declaring and setting a handful of float variables and only using those to set knob sizes.

I still would prefer to specify sizes in code rather than use SVGs. Otherwise, if I want to change the design of a family of knobs of different sizes, I have to do it on a per-file basis. I also have no idea how to paint in framebuffers, but maybe it requires learning how to use NanoVG. For the TransformWidget option, I suppose I’d have to make each of my widgets children of some TransformWidget-flavoured struct. That almost sounds doable even with my lacking knowledge, but I looked at the Doxygen page for TransformWidget (VCV Rack API: rack::widget::TransformWidget Struct Reference), and:

Transforms appearance only, not positions of events.

Does that mean that clickable areas wouldn’t be transformed?

I don’t think I’m at “adding cool stuff to useful libraries” levels yet, though I can still try to build something to start with and send the code over.

1 Like

There’s the fully self drawing no svf pixel as a template param knob I used for airwin. Noe t relies on the buffers draw widget from our rackhelpers lib we share with surge and a few others. May give you an idea what’s involved

1 Like

Thanks, though I still don’t understand how C++ templates work, I’ll try to see how I can use that. I’ve already managed to put together a text readout without any SVGs.

I aim to split the knobs I have into two parts (one rotating and one staying still), as I’ve seen others do that to display gradients that don’t move, and I think it’s efficient (there’s less to keep transforming).