Duplicating ofParameterGroup (or ofParameter)

Greetings,

on a project I worked on recently:

we had an issue where we kind of needed to make a duplicate of an ofParameterGroup. When you copy (ie, use the = operator) it’s really a shared_ptr, so changes in the original change the copy. Is there any convenient way (without iterating through the parameter group, which is kind of what we wound up doing) to make a duplicate which isn’t connected to the original ? I think what we were looking for is a sort of clone functionality…

thanks in advance!

no there’s not, the main usage of an ofParameterGroup is to group some parameters to access them from different places or attach listeners to them. we could add a clone functionality but can you explain the use case? there might be a different way to aolve the problem rather than cloning the parameters

so it was kind of an unusual situation – in this project, we had people create code sketches and use a parameter group to label what in the sketch should change.

the idea was that you’d see a kind of pseudo code on the right side with numbers that would update and on the left side you’d see visuals changing.

We then hooked this up to midi, to use a controller to record us changing the sketches, so we could animate the sketches. One issue was that when it was hooked up to midi, it felt like it needed smoothing every frame. We have over 50 sketches, so it was a pain to add new variables to each one to smooth, so i thought, “what if the midi alters an ‘unsmoothed’ version of the parameters and we just animate the original parameters to smooth towards the unsmoothed ones”. We tried adding smoothing on the midi side, but because that is an event based thing (vs frame based) it doesn’t work the same. In the end we had to do something like a clone but by hand.

I think this isn’t a common use case, but I could see quickly copying a parameter group and diffing them, or storing the parameter values at a specific point, being something that’s useful, etc.

I never really understood why chris decided to make the copy thing as when I left it, it was working with smoothing and all and it didn’t crash. I understand the idea of the duplication but what I implemented handled the parameters smoothing on a frame basis and worked well as far as I tested it.

As of the idea of cloning it sound like a bit impractical as the ofParameterGroup just stores pointers to ofParameters, hence cloning an ofParameterGroup would imply to create new instances of ofParameters somewhere else. The only thing that I imagine right now is to pass a vector<shared_ptr> to the clone function, which look like a very cumbersome thing to handle.
Best!

1 Like

I don’t really remember what happened with your code vs chris’s – it was a pretty insane sprint :slight_smile: I do remember at some point the smoothing wasn’t really working as expected and seemed to be event driven and not frame based. In the end, it wound up looking smooth and as expected.

At any rate, I have to say that I think having a clone() on a parameter could be pretty useful, same with an ofParameterGroup(…). This would be completely disconnected from events (ie, the clone wouldn’t be connected to any of the events of its originator), etc, and just copying the value, min and max of a parameter, and any other necessary fields. For example, you could record the parameter group at specific points in time, ie, setting keyframes, and then later use those values, etc.

Also generally, I’ve found it useful if I want to do simple diffing, vs using events, to be able to record snapshots.

Hi all,

Sorry for bringing this up again. I thought its better to keep my question here since it is very related.

I also would like to have a sort of clone functionality for ofParameterGroup which would make use of deep copies instead of shallow copies. Also I would like to make sure I can synchronize both copies in a user defined way. I will try to give a use case:

Lets say i have 100 floats in a group and i need to display them as strings (or some other heavier transformation) i would like this transformation to be done when the parameter is updated, and when the string is updated, but NOT on a per frame basis.

How would you go around this case?
The thing could get a bit more complicated if instead of only floats is a group of mixed parameters… but we can address that later.

The only solution I can think of is having two vectors and updating back and forth… but not sure if that is the best solution.

not sure why you need a copy in this case, can’t you just listen to the parameter changed event in the top group and only update the transformation when that happens? you can even have a second parameter group with the transformed values and the same names as in the original floats and only transform those that change like:

listener = groupFloats.parameterChangedE().newListener([&](ofAbstractParameter&p){
      auto v = p.cast<float>().get();
      auto str = ofToString(v);
      groupStrings.getString(p.getName()).set(str);
});
1 Like

Thank you!
You are right, no need for a copy in this case.
I rarely work with lambdas, so its really good to have a look at your example.

I have another similar case which i guess can be solved with the same solution.
I have a group of parameters that are being changed from OSC. The parameters will be used in a hardware, for example an array of switches. The hardware will respond if the parameter has been applied or not (sometimes switches are not available, or can’t change) and provide the current value in case the intended and the current differ. For that I will need again two groups of parameters that have to be updated back and forth.
I will go ahead and try with the same solution, although i guess some recursion issues could arise…

If any better ideas please let me know! Thank you!

recursion shouldn’t be a problem as parameters enter a mode of no event triggering while they are triggering an event so if you modify them from an event listener they won’t trigger one more event