I am trying to load a custom Svg as a light and have it change brightness(opacity) based on a module variable. the struct looks like this:
struct EnvLED : TSvgLight<RedGreenBlueLight> {
DobbsModule* module;
EnvLED() {
this->setSvg(Svg::load(asset::plugin(pluginInstance, "res/Source_File.svg")));
}
void draw(const DrawArgs& args) override {}
void drawLayer(const DrawArgs& args, int layer) override {
if (layer == 1) {
if (!sw->svg) return;
if (module) {
float lightval = module->BrightnessVariable;
//theres only one 'shape', but:
for (auto s = sw->svg->handle->shapes; s; s = s->next) {
s->fill.color = ((int)(lightval * 255) << 24) + (0 << 16) + ((int)this->color.g * 255 << 8) + 0; //Green Light with Alpha controlled by Variable
s->fill.type = NSVG_PAINT_COLOR;
}
nvgGlobalCompositeBlendFunc(args.vg, NVG_ONE_MINUS_DST_COLOR, NVG_ONE);
svgDraw(args.vg, sw->svg->handle);
drawHalo(args);
}
}
Widget::drawLayer(args, layer);
}
};
I’ve looked through the above post and others, and ended up essentially copying it’s structure over into my plugin, with no success. I am sure I am instantiating it wrong, determining location etc. wrong, or something like that, but it has been difficult to find any more relevant info.
Inside the PanelWidget, init looks like this:
if (module) {
EnvLED Main1;
Main1.box.pos = Vec(0, 30); //box.size should be automatically determined by the svg if i'm reading the sdk correctly
Main1.module = module;
}
that’s gone through many variations, from creating it as a pointer with createWidget, or just using new, to making the setSvg its own accessible function in an attempt to generalize it to be able to run different instances with different svgs. i just get empty space. What am I doing incorrectly here? is there a way to treat this more like a single light with setBrightness, and just use a GreenLight so I don’t have to bother with color generation?
the last sentence gave me a thought, so I repurposed an svgLight to load my file as its SVG, added it in the panel as you would a normal light, and set its brightness as usual. Now it shows up, and the underlying SVG shows up, but the light is still entirely circular(as is the halo, but that’s expected). this feels like it’s still loading a default file on top of mine. what do I need to subclass or override to fix that?
overriding the drawLight and drawHalo functions, and adding it as a Light child, the proper shape draws on the screen, on the lights layer even, but does not react to setBrightness in any way. I assume this has to do with the fact i’m drawing the shape with svgDraw and not altering the colors beforehand, but in order to do that I think I have to have an instance of the module in the struct to access the varaible from it, which I can’t do when building it purely as a light, unless of course there’s many ways to initialize that I do not know.
Solved it. Turned out pretty simple, if potentially inefficient, so I am sharing for others.
the struct itself is just an SvgWidget, like so:
struct SvgLED : SvgWidget {
ModulePointer* module;
int flag;
EnvLEDMain1() { }
void Svg(std::string path) {
this->setSvg(Svg::load(asset::plugin(pluginInstance, path)));
}
//drawing layer 1 for lights of course
void drawLayer(const DrawArgs& args, int layer) override {
nvgGlobalCompositeBlendFunc(args.vg, NVG_ONE_MINUS_DST_COLOR, NVG_ONE); //leftover from previous attempts, may or may not be helpful now in any way.
if (!svg) return;
if (module) {
//this loop is only really needed if the svg has multiple shapes
for (auto s = svg->handle->shapes; s; s = s->next) {
nvgStrokeWidth(args.vg, (s->strokeWidth));
float ModuleVariable = (module->SendingVariables[flag] ); //retrieve whatever value desired for use.
nvgFillColor(args.vg, nvgRGBAf(0.f, 1.f, 0.2f, enVal)); // put that where you want it
//this just 're-draws' the svg, which means you can change anything about it on the fly
for (auto p = s->paths; p; p = p->next) {
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, p->pts[0], p->pts[1]);
//I don't really understand this part, but I think it has something to do with the potential of Holes. it works either way...
for (auto i = 0; i < p->npts - 1; i += 3) {
float* path = &p->pts[i * 2];
nvgBezierTo(args.vg, path[2], path[3], path[4], path[5], path[6], path[7]);
}
if (p->closed)
nvgLineTo(args.vg, p->pts[0], p->pts[1]);
if (s->fill.type)
nvgFill(args.vg);
if (s->stroke.type)
nvgStroke(args.vg);
}
}
}
Widget::drawLayer(args, layer);
}
};
to instantiate within PanelWidget:
if (module) {
SvgLED* Led = createWidget<SvgLED>(Vec(location));
Led->Svg("path/to/file.svg");
Led->flag = 0; //flag for what element of arrayed variable to use for brightness
Led->module = module;
addChild(Led);
}