Is it possible to load a static panel image?

Is it possible to load a static PNG panel image in a simple manner? I.E., after loading an SVG file panel graphics, is it possible to replace the entire panel image with that from a PNG file?

Once again I am revisiting the elimination of global variables in my Meander module so that it does not have to run as a singleton. This is complicated by the fact that ~100% of Meander’s panel graphics are done proceedurally at run time via NVG. Only the panel size and background color is in the SVG file(s). It is difficult to get all situations working correctly, especially the browser view. It works fine now as a singleton, but it is complicated to get it all working. Currently my widgets have to render the panel graphics correctly for both when there is a module and when there is not. If I move all globals to the module level, it is very difficult to render everything correctly when I have no module as in the browser. I.E., the widgets and the module currently have access to the global variables and that works fine. As I imagine this new approach working, the widgets would use the module “globals” when there is a module and would just use the static panel image when there is no module as in the browser.

Please don’t spend too much time on this question. There are a lot of things that could prevent me from proceeding even if there is a way to load the PNG. Basically I’m seeking a proof of concept feedback here before I go further, again.

By the way, I’ve done this before and everything worked fine except when in the browser. At that time however, I was using a partially populated SVG file, but that info does not exist now.

Thanks

Put the ‘globals’ that are necessary for the rendering into a new class as a container for tjose variables. Put one of those in the module where the module can see it (if it needs it at all)

When the moduleWidget is constructed, it can store a pointer to the structure from within the module. but if there is no module, it can either construct one for itself, or use a global singleton of that container.

Given the circumstances of the ‘no module’ scenario, i think a singleton container should be fine for the browser.

1 Like

Yes, its eady to load a static png for a panel. There are quite a few blanking plates that do exactly that.

1 Like

Thanks. Do you happen to remember a blanking panel module that does this, so that I can look at the source code to get some ideas?

The one I know for certain is ModularFungi. But that code is not suitable for v2, so i wouldn’t particularly recommend it.

Load the bitmap with nvgCreateImage Draw it by creating an NVGPaint using nvgImagePattern, and then nvgFillPaint.

The nanoVG docs should cover it.

1 Like

Actually loadImage should be sufficient to load and cache the bitmap, rather than using nvgCreateImage directly.

You MUST NOT try caching the image yourself, the same as with fonts, because the context might be different when running under vst.

1 Like

Thanks David. I’ve tried this before and failed, which is why I think it would be beneficial to look at some functional code. Yeah, i had thought of the loadimage caching issue in V2.

I’m looking at your ModularFungi V1 code for ideas.

If anyone knows of an open source V2 plugin/module that loads PNG files as panel images, please let me know.

Thanks David. As mentioned, I succeeded in getting the globals encapsulated in classes (or structs) and had that all working correctly in all cases, but I could not draw the procedural panel when there was no module. I want to try the PNG panel image load first to see if I can get that going before I do anything else with global variables.

@k-chaffin

hi, i was able to load a png-file into a panel. A short time ago i released my module Pictogram on Github. It’s opensource so you can look at my code or even use it for your module. My module class stores a std::string filePath and in a Display class, that is a child of the main Widget class, there is a function drawLayer, that draws the image. And to test for a valid module pointer just place a:

if (!module)
   return;

at the top of function drawLayer, than nothing evil will happen. Than later in this function do:

    nvgSave(args.vg);
    nvgBeginPath(args.vg);
    // Make sure image is created only once after it was loaded
    // with module->loadSample(...). DrawLayer runs in a loop
    // at FPS-speed e.g. 60 frames per second!
    if (module->hasLoadedImage) //Is set in the module
    {
      // Should not run outside this "if" statement. It's too slow for that!
      imgHandle = nvgCreateImage(args.vg, module->imagePath.c_str(), 0);
     .
     .
      module->hasLoadedImage = false;
    }
    NVGpaint imgPaint = nvgImagePattern(args.vg, 0, 0, izx, izy,
                                        0, imgHandle, 1.0f);
    nvgRect(args.vg, 0, 0, izx, izy);
    nvgFillPaint(args.vg, imgPaint);
    nvgFill(args.vg);
    .
    nvgClosePath(args.vg);
    nvgRestore(args.vg);    

Good luck, Thomas :slight_smile:

1 Like

Thanks Thomas. I will dig into it.

If you’d like another example, Substation uses PNG graphics too. Here’s the relevant class

Header: dep/slime4rack/include/slime/widget/ImageWidget.hpp · main · Slime Child Audio / Substation for VCV Rack - Open Source · GitLab Source: dep/slime4rack/src/slime/widget/ImageWidget.cpp · main · Slime Child Audio / Substation for VCV Rack - Open Source · GitLab

1 Like

Thank you! I will take a look.

How certain are you about this? I’m having trouble with Image* and int .

Never used it. I used nvgCreateImage. I just found loadImage in the api.

1 Like

So, does this mean that it is necessary to have some “bitmap” library dependency in order to render a PNG file image onto a panel?

No, everything necessary is already in the usual plugin toolchain. The example from slimechildaudio looks good to me. You load the image into the context, modularfungi used png files. Then you create a fill texture from the loaded image, and use that to fill a rectangle.

1 Like

Thanks. Yes, @slimechildaudio does what I want (combine an svg and a png), but is fairly involved.

@Thomas_Michels uses a PNG library.

I’ll keep plugging away.

I’m not sure what you mean about 'combine an svg and a png. ’

1 Like

SVG files are markup, it is possible to embed a bitmap image within an SVG, don’t know if that is supported by nvg/vcv

You can check an SVG for embedded bitmap images by opening them with a text editor to see if there is a load of hex data in them

edit: some info, combine a data uri with the embedded rasta image 31: You Can Put Raster Images in SVG | CSS-Tricks - CSS-Tricks & 09: SVG with Data URIs | CSS-Tricks - CSS-Tricks this Stackoverflow has examples Does SVG support embedding of bitmap images? - Stack Overflow

1 Like

@slimechildaudio supports reading from an SVG file, adding a PNG file and adding a border, compositing into the panel background. I don’t necessarily need to do all of those things, but one approach is to read my SVG file that only has panel size and background color in it and use that to create the panel and set the background color and then read my light or dark static PNG panel capture images and either add that to the SVG panel background image or just replace the panel background entirely.

I’m still looking at your ModularFungi V1 code and how you use textures, but with changes for V2 such that I do not cache the image or texture that is created per frame in a widget from the current context.

Anyway, I have 3 good examples to work from, so I will get it figured out. Thank all three of you. @Thomas_Michels