i’m struggling with dynamic pins, yes…it has been done before but i miss some lines of comments in the template and most github code is doing a lot of special stuff. oh, and yes …i’m still on the c# learning curve.
what i have so far
a IIOContainer spread of bools (pins will be bool)
a config pin holding some json, containing the future pin names
i have an event / method looking for the change of this config pin
what i don’t get is how to manage this IIOContainer spread safely hence adding, removing pins in no order, depending on what’s going on in the json. i can turn the json names into a list. but how to go from there ?
cheers
ps: especially things like
Func<int, IOAttribute> ioAttributeFactory) where T : class
i usually keep the IIOContainers in a dictionary with the name (or more if needed) as key. so on each config change check whether pin needs to stay, be disposed or created newly.
does that answer the question or is more about how to handle the factorymethods?
yes, that makes it a little more clear and still confuses me…
like this
protected Dictionary<string, IIOContainer> FPins = new Dictionary<string, IIOContainer>();
and adding a pin is
FPins.Add(name, null);
but,why null (IIOContainer Value). and how can a dictionary actually define pins ? the relation is not clear since i thought a dictionary is just a place to store data.
if you have a really stripped down commented example of how a dictionary works with this IIOContainer, it may help understand it.
Dictionary<string, IIOContainer> FPins = new Dictionary<string, IIOContainer>();
(FInput.IsChanged)
{
//delete pins which are not in the new list
foreach (var name in FPins.Keys)
if (FInput.IndexOf(name) == -1)
FPins[name](name).Dispose();
Dictionary<string, IIOContainer> newPins = new Dictionary<string, IIOContainer>();
foreach (var name in FInput)
{
if (!string.IsNullOrEmpty(name)) //ignore empty slices
{
if (FPins.ContainsKey(name)) //pin already exists, copy to new dict
{
newPins.Add(name, FPins[name](name));
FPins.Remove(name);
}
else if (!newPins.ContainsKey(name)) //just checking in case of duplicate names
{
var attr = new InputAttribute(name);
var type = typeof(ISpread<bool>);
var container = FFactory.CreateIOContainer(type, attr);
newPins.Add(name, container);
}
}
}
//FPins now only holds disposed IIOContainers, since we copied the reusable ones to newPins
FPins = newPins;
}
it does kinda work now, but i loose my connections on patch startup. if this code part is not executed on startup, is this the expected behaviour ?
what should i consider to keep the connections of dynamic pins ? the dictionary is obviously empty in the first place and will be filled once the config pin changes. is this the problem ?
I made a library to make dynamic pins or other pin juggling easier during development called PDDN (Pin-Dictionary-Dynamic-Node). Among other things it has a class “PinDictionary” which provides dictionaries for output and input pins and complimentary methods to manage them (create pins or destroy). It gives you non-generic spreads (slices are objects), supports DiffSpreads and binsized spreads too.
for the other problem same library contains an abstract class “ConfigurableDynamicPinNode” which takes care of the disconnecting behavior.
sources are here: https://github.com/microdee/mp.essentials/tree/master/src/PDDN/PDDN
binary is here: https://github.com/microdee/mp.essentials/tree/master/nodes/plugins/generic
nuget package is coming soon
since your pin configuration is just dependent on a spread of strings, copy the pin to a config pin, and use the values of the config pin on plugin creation to have the saved pins ready.
config pins are called when vvvv is creating its graph (preparegraph), so this is the point where you have to have your pins ready. guess atm you create your pins in evaluate (since you are accessing FInput), which happens at another point in time of a frame
as i said, i’m using a config pin to save the string values and i’m aware of the config pin behaviour on startup. i’m not doing anything in evaluate. probably a minor error which i don’t see right now.
i’m not using FInput, this is your code ;)
is onimportsatified the first place to create the dynamic pins on startup? or should i create an event and raise the evnt on startup. so many things to do wrong…
so you’re listening to DiffPin.Changed event i guess?
that’s exactly the time to do the pin setup without loosing links. you might want to check if the incoming spread is filled with the default string. happens, that the event triggers twice, once without actual values, the second time with.
something like that and you should be safe. note that you’d better not just copy paste these lines, they’re just written out of memory. but this way works for out for me, safe for production
OnImportsSatisfied is a bit to early to create the pins, since the config pins are not yet ‘filled’ with the data of your v4p file