How do I decorate a push-button even when lit?

In a new module I’m developing, I have a VCVLightBezelLatch, and it works great as a push-button control that lights up when “on” and goes dark when “off”.

I have received feedback from pre-release testers that it would be helpful to superimpose the international power on/off symbol “⏻” on the button. After looking at the code for VCVLightBezelLatch, I came up with my own version that looks like this:

struct SapphireLightBezel : app::SvgSwitch
{
    app::ModuleLightWidget* light;

    SapphireLightBezel()
    {
        momentary = false;
        latch = true;
        addFrame(Svg::load(asset::plugin(pluginInstance, "res/power.svg")));

        light = new GrayModuleLightWidget;
        light->addBaseColor(nvgRGBA(0xff, 0xff, 0xff, 0xc0));
        light->borderColor = color::BLACK_TRANSPARENT;
        light->bgColor = color::BLACK_TRANSPARENT;
		light->box.size = math::Vec(17.545, 17.545);
        light->box.pos = box.size.div(2).minus(light->box.size.div(2));
        addChild(light);
    }

    app::ModuleLightWidget* getLight()
    {
        return light;
    }
};

My file res/power.svg is just like the file res/ComponentLibrary/VCVBezel.svg that comes with VCV Rack, only I added the aforementioned ⏻ Unicode character converted to an SVG path, centered on the button.

Anyway, it looks fine when the button is off. But when the button is on (the light is lit), the power symbol gets washed out. As you can see in the code above, I tried making the light’s base color semi-transparent: light->addBaseColor(nvgRGBA(0xff, 0xff, 0xff, 0xc0)); I end up with a dilemma: either it’s too transparent (alpha much lower than 0xc0), and the light is hard to see, or it’s not transparent enough and the power symbol becomes hard to see.

One idea I have now is to draw the “⏻” on top of everything else somehow. But I have no clue how to do that. So my overall question is, what is the best way to show the power symbol on top of the button whether or not the light is turned on? My secondary question is, if the idea of drawing the character/path myself on top of the button and light will work, how do I do that? Just a pointer to any existing code I can look at would be great.

Thanks!

1 Like

I would override drawHalo() to do nothing.

I tried that, and it just makes the halo disappear, which I would rather keep. The power glyph still gets washed out by the light itself. However, the suggestion did spark an idea I will try:

struct SapphireLight : GrayModuleLightWidget
{
    void drawHalo(const DrawArgs& args) override
    {
        LightWidget::drawHalo(args);
        // ... somehow draw the power glyph on top? ...
    }
};

If I can figure out how render an SVG path where the comment placeholder is above, this might just work. I’m hoping drawHalo is called only when necessary, and not on every single rendering frame.

So I’m still interested in guidance from the more experienced VCV Rack developers here. Am I barking up the wrong tree, or am I getting closer?

most devs don’t make custom controls, I think.

I implemented something sort of like this, except in my case the buttons are stenciled black so that the button’s symbol (such as ⏻) is emitting light rather than blocking it.

It’s been a while so I’m fuzzy on the details, but the gist is that I created an SvgLight subclass of rack::SvgWidget which draws its SVG on Layer 1 instead of Layer 0. Then I subclassed rack::SvgSwitch as SvgLightSwitch which holds an SvgLight inside.

You can find some example code here, as it stands in the stable version of Algomorph. Excuse the unused stuff for drawing an SVG halo.

1 Like

I love this, thanks. There is a gold mine of techniques for light knobs and light switches. I’ve been wanting something like this!

1 Like