Is it possible to load a static panel image?

I now have the static PNG images displaying on the panel so I have a proof of concept and now need to flesh this all out. The static images should only render when in the module browser.

If you copy the code from the widget, along with the header code, you shouldn’t get any crashes.

1 Like

The more the merrier! :slightly_smiling_face:

2 Likes

I should note here that I ended up using the loadImage() functionality which in the end is almost trivial to get working with nanoVG since no other “bitmap” functionality has to be added. Care does have to be given to not caching the image and checking for image pointer validity before using it. So, it all works just like loadFont(), more or less.

My development version of Meander now draws the panel procedurally as long as there is a module. If there is not a module (e.g. in the browser), it loads and draws a static PNG file which is a screen capture of the executing Meander panel for both light and dark themes.

This will simplify my code where I currently have to do some procedural drawing even in the browser view.

2 Likes

Turns out Rack renders paramWidgets, lightWidgets and portWidgets last, perhaps in a layer(?). As a result, after I render my static PNG file image as the panel image, Rack renders all of the above widgets on top of the panel image “layer” . This makes sense for using image files rather than SVG files, but makes less sense for what I am doing by only rendering the static PNG image when in the browser.

This is a subtle result since the widgets align with the panel image and it is working fine except for that.

Does anyone know if I can suppress the rendering of the above widgets if my module is null? I see some mention of “layers” here in the development discussions, but I cannot find anything in the API documentation.

In that case, surely you don’t need to attach your paramWidgets, lightWidgets or portWidgets if you are in the browser.

1 Like

If you really want to add them as children, but not show them, they probably have a visible property. But it would be easier not to add them in the first place.

1 Like

I try to never do if (module) draw() kind of things. When I’m good I try to make all my widgets draw something so they look ok in the browser.

I do notice that a lot of modules show up sort of “blank” in the browser, presumably because they don’t draw when module == nullptr.

1 Like

That’s correct, but I would need to make drastic changes to my module to not attach the widgets when in the browser.

I’ll probably leave it as it is since it looks fine but is just doing unnecessary steps when in the browser.

Thanks.

1 Like

Right. I have a significant amount of code to have the module widget look good in the browser.

Thanks.

1 Like

I would guess the module picture is rendered once when the module is updated in the library and then that images is served by the library, so a little bit of extra work here seems pretty minor.

1 Like

Edit: what I said is not entirely right. See @carbon14 and @Ahornberg comments following.

The module image in the browser is captured from the current module instance at runtime. But it is cached and it is not clear what controls the cache refresh. I manually toggle the zoom in the browser to force a cache refresh or otherwise the current panel theme color may not match the browser module color theme. I’m not sure if there is a way to tell the cache to refresh from within the module when the panel theme is manually changed.

The module image in the library is likewise captured from an executing module instance as part of the library build tool chain when a new version is built. So, yeah, coding the module to appear nice in the browser also results in it appearing nice in the library. My Meander module looks slightly different in the library than in the browser. That appears to be due to how the image is captured or rather when. Seems like not everything is initialized when the library image is captured, perhaps due to the large code size of Meander which probably takes longer to load and initialize than most.

I think we are saying the same thing, but I thought I would expand upon this with my understanding in case others are interested, or in case I have something wrong and someone will educate me.

1 Like

I don’t believe that there is any way to force the module browser to reload it’s images when you change your panel theme.

I think you are slightly wrong when you suggest that the image in the browser is ‘captured from the current module instance at runtime’

An instance of your ModuleWidget is specifically instantiated for the benefit of the browser. It is asked to render once into a framebuffer. Quite likely it is then discarded.

A similar thing happens for the library images, the ModuleWidget is instantiated, it’s draw method is called and then it gets thrown away.

2 Likes

The module browser is created only once and the module-widgets are created lazily, but once created, they are cached.

My modules FlyingFader and TapeRecorder display random colored elements in the browser each time you restart the rack completely.

So far I didn’t find a way to display different colored elements each time the broser widget is opened.

1 Like

Ah, that makes sense. I think I meant what you said, but I was hazy. Thanks for clarifying.

Thanks for clarifying.

I found a way to change the module widget in the browser dynamically:

By overriding step() on your module widget, you can change everything inside your module widget and its children at GUI frame rate.

By creating a DirtyEvent and calling parent->parent->onDirty() you set the FrameBufferWidget in the Browser that holds your module widget to dirty, so that it redraws iself and all its children (your module widget and its children).

In the video above, I randomly reload the SVG file and run a counter in a widget with a custom draw() method.

Here’s a pseudo-code:

void MyWidget::step() {
	if (!module) {
		// update your child widgets here
		// e.g. load an SVG file or change internal values
		DirtyEvent eDirty;
		parent->parent->onDirty(eDirty);
	}
	ModuleWidget::step();
}
2 Likes

That is great. I already do some of my panel theme logic in ::step() override. I’ll see if I can force the browser module graphics to redraw on dirty. I have Meander torn apart currently as I am changing from a singleton module to a multi-instance module, so it might be a few days before I try this trick.

Thank you very much!

2 Likes

This works like a charm in my Meander browser mode use of a static panel PNG file in the proper panel theme color! No more having to manually refresh the browser panel image cache via zoom.

The only change I made was to explicitly override step().

Thanks for coming up with this!

1 Like

Unfortunately, this parent->parent->onDirty() technique causes serious performance issues for all users in the browser.

1 Like