Modules that work with Modular Fungi LightsOff

Modular Fungi has a pretty interesting module called LightsOff that allows the user to set a global “dark mode” that dims the screen and only shows lights and ports. Some modules don’t work perfectly with it currently.

2 Likes

If motivated users would file github issues against offending modules it would be a big help.

1 Like

I have done all the leds displays in Impromptu and the VU meters in MindMeld, but had no success with the main screen in EqMaster. If I remove the nanovg scissoring I use in that display, it works, but then the display area is not clipped, which is bad. And I know it should work, since I have seen the Fundamental Scope modified by @contemporaryinsanity and that display does have scissoring, so more investigation is needed.

3 Likes

I contributed this module to Omri‘s Modular Fungi plugin. As @computerscare stated correctly in another thread there is no great magic going on: A translucent rectangle on top „dims“ everything down and all LightWidgets are drawn a second time above it. This method is not very efficient but it is the only way I could find to realize Omri‘s imagination of his „lights off mode“ in Rack.

I had not much time in the last few weeks but I will try to sort problems out if some widgets are not drawn correctly!

2 Likes

I don’t think it’s fair to consider incompatible modules to be offending, when we didn’t expect that LightWidget would be a semantic rather than a display thing, or fair to expect the dev community to support what’s mostly a neat hack / easter egg.

Personally, fixing my existing modules, and the one I’m currently developing, will be a lot of work. Almost all my collection breaks with the lights off.

The lit piano keys (which can have 2 different light colors) on quack are derived from SvgSwitch, because it’s way easier to implement that way. There’s no easy way to make it clear that the 2nd and 3rd frame emit light, but the first doesn’t.

My LCD should be trivial to make compatible simply by subclassing LightWidget and overriding behavior that breaks, if any. But that’s assuming it works through framebuffers.

The segment display will be harder, because the lit parts at the bottom aren’t toggled, for simplicity I baked the unlit version in the background and overlay the lit version, and it’s not subpixel-precise, so making the text part transparent would look bad at low resolution.

image

Finally, the lit buttons and knobs in Darius are simply made by overlaying a transparent knob over a LightWidget. Which is… Pretty much how you’d do it in real life, right?

I’m willing to support lights off, though. But I could use clear guidelines and an alternative to subclassing LightWidget to tell it something emits light. And also a way to tell it that a widget should be re-drawn, unlit, over the lights.

4 Likes

Done here, works fine.

I didn’t mean to suggest that. github issues are also for feature requests. Myself, I would consider this a feature request. If someone logged one on my github I would probably eventually look at it and see if I can do it easily. If so, sure. If not, no.

1 Like

I tried it :wink:

Thanks. When I go back to “home” computer I can log into github and respond. If you could add a note about which module you are referring to and what you would like it to do that it isn’t doing that would be a big help.

After trying out making things compatible and realizing I’d have to rewrite a lot to make it happen, I think what we really need isn’t for lights off to be smarter, but to provide us with a way to tag any widget with one of those two properties:

  • This widget emits light
  • This widget partially covers a light but emits none
5 Likes

I agree. My C++ knowledge is not deep enough to suggest something smart, I think. Someone?

An observation / suggestion: LEDs that are off should have their brightness reduced / zeroed, real LEDs don’t emit light when off.

Just an idea to start the conversation, that will probably require some discussion.

As a fair few modules are updating to accommodate LightsOff, maybe those modules could save a parameter in the json to subscribe to the service, may be saved in the json with the name “USE_LIGHTSOFF”, then only redraw the lights of modules that subscribe.

example json extract:

        {
          "id": 17,
          "value": 0.0
        }
      ],
      "data": {
        "USE_LIGHTSOFF": 1,
      },
      "pos": [
        88,
        1

LightsOff module can now be moved around :slight_smile:

Another problem I’m encountering is that Lights Off, when active, coerces my widgets to be visible.

image

image

This is how they are implemented - copying it here for reference since I’ll revert to inherit from SvgWidget, it’s honestly too much effort to support this, I have to rewrite so much for so many components.

// SvgWidget edited to inherit from LightWidget instead, for Lights Off support.
struct LitSvgWidget : LightWidget {
	std::shared_ptr<Svg> svg;

    void wrap() {
        if (svg && svg->handle) {
            box.size = math::Vec(svg->handle->width, svg->handle->height);
        }
        else {
            box.size = math::Vec();
        }
    }

    void setSvg(std::shared_ptr<Svg> svg) {
        this->svg = svg;
        wrap();
    }

    void draw(const DrawArgs& args) override {
        if (svg && svg->handle) {
            svgDraw(args.vg, svg->handle);
        }
    }
};

// The QUEUE message on the segment display
template <typename TModule>
struct QueueWidget : TransparentWidget {
	TModule* module;
    size_t node;
	FramebufferWidget* framebuffer;
	LitSvgWidget* svgWidget;
    bool lastStatus;

    QueueWidget() {
        framebuffer = new widget::FramebufferWidget;
        addChild(framebuffer);
        svgWidget = new LitSvgWidget;
        svgWidget->setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/components/solomon-queue-lit.svg")));
        framebuffer->box.size = svgWidget->box.size;
        box.size = svgWidget->box.size;
        framebuffer->addChild(svgWidget);
        lastStatus = true;
    }

    void step() override {
        if(module) {
            if (module->queue[node] != lastStatus) {
                framebuffer->visible = (module->queue[node] == true) ? true : false;
            }
            lastStatus = module->queue[node];
        }
        Widget::step();
    }
};
1 Like

After reworking my personal component library, I’ve got most of it working:

Here’s what I did - and I have no clue whether i did it in a sensible way or one that will cause issues.

I use a custom ModuleWidget to be able to define my own helpers.

I have a LitSvgWidget that’s pretty much a SvgWidget but made to inherit from LightWidget.

I have a LitSvgSwitch where the first frame is always displayed normally, then subsequent frames are shown on a LitSvgWidget instead.

The LEDs behind the jacks are cut off with nvgPathWinding. A helper function allows me to add jacks to modules in a single function, taking one additional parameter than usual, for the light:

addDynamicOutput(mm2px(Vec(3.52f,  80.9f)), module, Splirge::SPLIT_OUTPUT + 0, Splirge::SPLIT_LIGHT + 0);

The knob lights are passed a pointer to the paramQuantity and have a little dark segment drawn on them so they continue to work in Lights Off mode:

if (module && paramQuantity) {
    nvgBeginPath(args.vg);
    nvgMoveTo(args.vg, mm2px(4.f), mm2px(4.f));
    // Rotates by -90 degrees in radians
    float value = rescale(paramQuantity->getValue(), min, max, -0.83f * M_PI - 1.570796f, 0.83f * M_PI - 1.570796f);
    float targetX = mm2px(4.f + 3.2f * cos(value));
    float targetY = mm2px(4.f + 3.2f * sin(value));
    nvgLineTo(args.vg, targetX, targetY);
    nvgStrokeColor(args.vg, nvgRGB(0x33, 0x00, 0x00));
    nvgStrokeWidth(args.vg, 2.f);
    nvgStroke(args.vg);
}     

Full code:

5 Likes

Another frustration I’m encountering: I can’t control the order in which lights overlap each other in Lights Off.

image image

I can solve it by cutting out those buttons properly, but it’s gonna be at the expense of making my components less re-usable.

1 Like