On the use of hardcoded text widgets vs SVG texts

I generally prefer the idea of using hardcoded text widgets for port names and such, rather than writing the text on the SVG directly and making it a path. It allows more flexibility, at least in an early development stage.
However, I’m wondering about the CPU overhead of this solution. Does anyone has some data? I expect the graphics engine will be more optimized in drawing an SVG path rather than processing my custom code based on nanovg.
Regards

1 Like

At this time, Label calls nvgText every frame. SvgPanel on the other hand renders to a FramebufferWidget and is as fast as it’ll get.

1 Like

@leodardo I also find it really hard to work with SVG rather than nanovg but as @Vortico says you have to put things in framebuffers.

For the sets of plugins I wrote, I found myself writing a little widget which is a FramebufferWidget and has a transaparentwidget and a lambda.

This means you can do something like

addChild( new BufferedWidget(pos, size, [](NVGcontext *vg) {
      NvgBeginPath(vg);
      NvgRegt(vg, 0,0,10,10:
      // etc...
  }
)

And your code only runs when the UI invalidates. This lets you very easily prototype custom UI components in C++ code and also get minimal repaints.

Hope that helps.

1 Like

Thanks for the answers.
I thought about something like a buffered widget but haven’t had the time to experiment myself. Very cool.

Cool. Well the surge-rack code is all GPL3 (as is the BaconPlugs software where I did the first version of that technique) so if that’s compatible with your license, feel free to just copy it directly into your codebase. If not you can at least look at it and figure out how to do something “similar”.

@Vortico: I’m taking this thread to mean that it’s a bad idea to use a lot of Labels. And “somebody should” write a Label that uses a FrameBufferWidget. yes?

1 Like

The approach I took in BaconMusic was to make a single FB-wrapped widget for my background and then if you add children to that FB-wrapped widget they ride along with the FB-ness.

In surge-rack i didn’t even bother with that and just do everything with draw lambdas. But I wrote surge-rack way more recently.

Sure, that’s great, and it’s great people can take your work and use it. But I’m going to guess that maybe half the VCV devs are like me - into DSP and optimized coding, not really into writing UI code. I tend to use the stock UI widgets 90% the time, and use a lot of Labels. Again, not everyone does that, but I think many do.

Yeah right. I and it is clumsy to always remember to add a frame buffer if you don’t remember. I didn’t at first and always worry I will forget one. It did feel a bit odd having to make that pattern

Maybe if there was a function like addchild which injected the fbw that would be best. Such a function is trivial to write in a plugin but may be hard to position in the codebase. I can imagine the argument that addchild is in widget and widget doesn’t know about framebuffer.

But nothing stopping you from making addbufferedchild in your plugin which takes a widget makes a framebuffer adds the widget to the framebuffer with pos reset to 0 sets the size of the framebuffer size to size and pos to pos then adds the framebuffer instead - which is what it seems you are after.

Having a graphic designer makes the panel workflow easy, but even if you don’t work with one, you can be your own designer by switching to strictly “design mode” for a bit. I believe this design-first approach (and finalize the design before writing your first line of code!) gives fantastic results and is far more efficient than merging the design and implementation processes.
Doing this allows you to bake the text into the panel, which looks better and gives a more polished look with your own choices of fonts, size, etc.

4 Likes

I 100% agree with you. And the new version of my modules and the surge rack modules both had this workflow. (With surge rack we had the code ahead of the modules because we were adapting an existing synth).

Just I find emacs is a way easier way to output the nvg commands I want rack to run than Inkscape! I think that’s where the need comes from.

I agree that this is the right procedure for commercial purposes and, of course, any hardware product should follow the same process ideally.
However, just for the sake of discussing, a software product with an open SDK is a perfect tool for rapid prototyping of algorithms, and a perfect companion for educational and academic purposes. I think the serial approach you are suggesting simply doesn’t fit with that use case although marginal they may be. I also think it breaks with modern software design methodologies based on concurrency and iterative development cycles. Enforcing an old-school hardware approach may be good in some sense (and I’m all for it), but not fit all necessities, especially in this era of accelerated product development cycles. Just my 50 cents.

I don’t really see how this is an argument for recommending programmatic Labels rather than baking text in SVG. Changing and positioning text with Inkscape is easier regardless of your development process.

Some time ago I wrote a script for an upcoming module with a lot of text and knobs:


This converts all text elements of a SVG file to objects and also outputs the coordinates of circles in a header file. In the “description” field in Inkscape I can enter e.g. this text:

name VCO_2_WAVE
ofs -4.75 -100.6

and then in the generated header file this is generated (the offset is relative to the absolute circle coordinates for different controls) :

#define VCO_2_WAVE_POS Vec(385.167836, 238.425235)

I can then just use it in the module definition like this:

addParam(createParam<Davies1900hBlackKnob>(VCO_2_WAVE_POS, module, FB15::VCO_2_WAVE_PARAM));

This allows me to move everything around and change text easily, without the need to manually fix coordinates or change all text to objects. Big upfront design with thinking first of all functionality of something and then drawing the final panel doesn’t work for me, I develop things incrementally.

1 Like

Are you aware of ./helper.py, included in the Rack SDK? https://vcvrack.com/manual/PanelTutorial.html#adding-components

Thanks, looks good for initial module creation. But you added it in February, was not there 11 months ago when I created my script :slightly_smiling_face: Also looks like it doesn’t work with my incremental work style, because it overwrites the C++ file, and it doesn’t convert text to objects. But good idea with the color coding for different component types, I might use this in my script.

It’s been around for a while, but it was called panel2source.py (don’t use that link, obsoleted by helper.py).