Local Look and Feel Bleed Through
-
Here's my issue.
I have a control helper inline function which basically goes like this
inline function createKnob(param) { local widget = {}; widget.ref = Content.addKnob(param.id, param.x, param.y); widget.data = {}; // initialize the data object //.......... a bunch of other stuff copying properties from the //input param object into widget.data object }
The function takes a JSON object where I give it a bunch of parameters, it's nice an clear when reading through it.
I have a local look and feel setup for the slider which exists in a function
inline function settingsSlider(widget) { local laf = Content.createLocalLookAndFeel(); laf.registerFunction("drawRotarySlider", function[widget](g, obj) { ..... draw stuff } return laf; }
and I assign it as you would expect
slider1.ref.setLocalLookAndFeel(settingsSlider(slider1));
The reason I'm encapsulating local LAF creation and passing it the widget reference is because I want to access the .data object from inside the look and feel function.
This works perfectly fine with a paint routine and a panel.
But using a slider and LAF breaks shit as soon as there's more than one of the sliders.
if I now create 10 sliders using the helper function, any references to
widget
from any of the look and feel functions in any of the 10 sliders will only point to the lasts created slider, i.e. the one that had its setLocalLookAndFeel method called last. So widget.data.prefix takes the prefix property of the input param object (that I store into widget.data.prefix) of the last one.References to the obj object inside the function works fine, but I can't store my metadata there.
So the function can tell that it's in the proper component as the obj properties are all correct, like obj.valueNormalized, obj.text etc. But
widget
always points to the last declared slider.Again, this setup works for a panel and a paint routine. Am I missing something here?
Thanks for bearing with me.
-
You're over-relying on the lambda concept here - it's only supposed to carry locally scoped data into a locally executed sub function, but if the lifetime of the function exceeds the lifetime of the variable you pass into the brackets, you're in undefined behaviour territory and a lesser framework than the eternally graceful HISE might crash instead of behaving weird.
Also your concept of tucking together a JSON object and the component reference and then trying to treat that as the "main" object leaves a lot of low-hanging fruit options unused. I would recommend detaching those and running your own data model that stores additional data for each component in a separate JSON object. Then you can just fetch your additional data inside the look and feel functions without having to pass anything around in lambdas.
// This namespace encapsulates a JSON object that contains additional data for each UI component that can be queried using the ID of the component namespace CustomContent { // PUBLIC Interface // Return the JSON item for the given component id // It will create the object on the first use inline function:JSON getComponent(name:string) { local p = __obj[name]; if(!isDefined(p)) { p = {}; __obj[name] = p; } return p; } // PRIVATE Implementation, keep going nothing to see here... const var __obj = {}; } const var laf = Content.createLocalLookAndFeel(); laf.registerFunction("drawRotarySlider", function(g, obj) { // we use the obj.id property to get the custom data JSON g.fillAll(CustomContent.getComponent(obj.id).specialColour); }); inline function createWidget(name, specialColour) { local w = Content.addKnob(name, Math.randInt(0, 4) * 128, 0); CustomContent.getComponent(name).specialColour = specialColour; w.setLocalLookAndFeel(laf); }; createWidget("YELLOW", Colours.yellow); createWidget("BLUE", Colours.blue); createWidget("RED", Colours.green); createWidget("GREEN", Colours.red); // failed on the last two lines lol...
-