ofParameter

There was some chatter a while back (memo especially) about a parameter register built into oF (or as an ofx)
The main point is to create a global register of parameters that can be of a bunch of useful types (floats, ofVec3f’s, etc)
Each parameter has a name and a value
This kind of functionality is commonly handled by gui’s, but many possibilities would be opened up if this was extension agnostic (e.g. extensions could communicate via parameters, sample apps could use parameter lists and users could easily switch out different gui’s)

On the plane i knocked out the following outline of functionality i’d like:
• ofxParameter
• Problem
• Trivial saving / loading of parameters
• Creating user controls for parameters
• Extension agnostic (gui’s, timelines, etc)
• Grouping parameters
• Features
• Instantiate and access have same syntax
• Save / Load / Autosave
• Global parameter register
• Folders / Subregisters / Tags
• Remote network access
• Enumerate parameters
• Tags
• By default every param has ‘user’ tag
• “user,timeline1” refers to
• During instantiation
• create parameter with both tags
• During access
• Parameters containing both tags
• Alternative names
• Control
• Argument
• Tweak
• InteractiveVariable
• Fiddle
• Variable
• Syntax
• Instantiation / access
• ofParam[string parameter, string tag=“user”]
• E.g.
• ofParam[“myValue”]
• Equivalent allocation
• ofParam[“v”]
• ofParam<float*>[“v”, 3]
• ofParam<T*>[string parameter, int allocationSize=3, string tag=“user”]
• File
• ofParamSave() / ofParamLoad()
• ofParametersSave(string filename=“parameters.XML”)
• ofParamSetAutoSave(bool b=true, string filename=“parameters.xml”)
• ofParamSetSaveable(string parameter, bool saveable)
• Tags
• ofParamAddTag(string paramName, string tag)
• ofParamRemoveTag(string paramName, string tag)
• Listing
• vector ofParameterGetList(string tag=“user”)
• if tag="*" then we return all parameters
• Debug
• ofParameterSetAccessCountEnabled(bool b)
• Turns on access counting.
When enabled, we count how many accesses we make to each variable per frame
• ofParameterGetAccessCount(string param, bool cached=true)
• Returns how many times a parameter has been accessed in a frame,

If we use ‘cached’, then we report the value from the previous frame, else we return the current count for the current frame (this obviously is affected depending on where this debug function is called within the current frame)
• ofParameterSetTimestampEnabled(bool b)
• ofParameter class
• vector tags
• void* data
• unsigned int dataSize
• bool saveable
• unsigned int timestamp
• unsigned short accessCount

Note that memo was suggesting using Poco::Any instead of pointers for storage
There probably is something better than what i’ve outlined above
Especially strings would be difficult to work with if we just use simple memory allocation.

I often find this would be incredibly useful if it was standardised and flexible.

loves
Elliot

Intriguing concept.
I think you would also need getter/setter function for the data and tags, otherwise you’d have to overload every single function where you want to pass an ofParam, or have to cast all the time.

One thing I don’t get, I think: Is this primarily meant as a container of sorts, as an easy collection of all used (global) variables? Because “normal” variables you currently use are also extension agnostic, no? What’s the advantage, e.g. for switching out GUI’s? How would that look like? Currently, you can pass a string to one or another addon, afterwards you pass an ofParam containing a string to one or the other…what am I missing here?

the extension agnostic thing would be like:

gui example:
developer A makes an example with some parameters
they define them using ofParameter rather than simple floats, etc
rather than telling the gui which parameters will be shown on the gui, automatically all ofParameter’s (with tag “user”) are enumerated on the gui

developer B gets the demo, but doesn’t like the gui from developer A (or otherwise chooses to work without it)
developer B now switches out developer A’s gui in one line of code
extension<>extension example:
A character animation extension enumerates all the bones on a character as ofParamters with relevant tags (e.g. “ofxCharachterAnimation”, “joints”, “left knee”).

Then user brings in ofxTimeline

ofxTimeline then can automatically enumerate all the joints from ofxCharachterAnimation without any development in ‘testApp’ or any codependency between the two projects.
User can select onscreen ‘add a new track in ofxTimeline for the left knee parameter’. ofxTimeline then uses ofParameters to store which tracks are in use / which parameters they are associated with, etc. these parameters are tagged as “ofxTimeline” “settings”

hey Elliot,

Just getting a chance to look into this. I think it’s a really useful concept.

To get buy in from people you and I could make a convincing example. I’m willing to make ofxTimeline dependent on this. And make a version of ofxControlPanel and ofxSimpleGuioToo use it too.

Also then I could make ofxNetworkedParameter work with it!

If we did all of this we may be in a good place to put it in the core. i have a feeling openFrameworks 008 will be 2d and 3d user interaction stuff (like we are talking about earlier), so making convincing strides in this area will help sway the case when we want to make it core

How is this thing coming along? I was thinking about doing something like this for some time but then I remembered this thread…

I think arturo finished the outstanding issues. it needs some testing though.
its sitting in this pull request: https://github.com/openframeworks/openFrameworks/pull/1397

Ah nice to see it is still under development. I think it is a great & needed feature.

I’ve extended ofParameter slightly to make it easy to interpolate or ease variables. The new functions are:

void lerpTo(ParameterType goToValue, int numFrames);
void easeTo(ParameterType goToValue, int numFrames);

There is a private update function which handles the interpolation formula (the first is linear, the second is a power formula for easing. There is an event listener for the main update function to run the interpolation in the background. So the user can just run one of the methods above and it will interpolate the value over the next n frames.

I though maybe it is a bit too specific for ofParameter and works better as an addon, but I also considered just adding this function directly to ofParameter to simplify things. the code looks like this:

template <typename ParameterType>
class ofxParameter : public ofParameter<ParameterType>
{
public:
    using ofParameter<ParameterType>::operator=;

    ofxParameter<ParameterType>() {
        ofAddListener(ofEvents().update, this, &ofxParameter::update);
        frame = 0.0;
        numFrames = 0;
    }

    void lerpTo(ParameterType goToValue, int numFrames) {
        setInterpolation(goToValue, numFrames, LERP);
    }

    void easeTo(ParameterType goToValue, int numFrames, float easeCoefficient=0.65) {
        this->easeCoefficient = easeCoefficient;
        setInterpolation(goToValue, numFrames, EASE);
    }

private:
    enum LerpType { LERP, EASE };

    void setInterpolation(ParameterType endValue, int numFrames, LerpType lerpType) {
        this->endValue = endValue;
        this->numFrames = numFrames;
        this->lerpType = lerpType;
        startValue = this->get();
        frame = 0.0;
    }

    void update(ofEventArgs &data) {
        if (frame++ < numFrames) {
            float t = lerpType==LERP ? frame/(numFrames-1) : pow(frame/(numFrames-1), easeCoefficient);
            this->set(startValue*(1.0f-t)+endValue*t);
        }
    }

    ParameterType startValue, endValue;
    float frame;
    int numFrames;
    LerpType lerpType;
    float easeCoefficient;
};
1 Like

the problem with this is that you can make an ofParameter for labels for example or any other type which won’t compile, it’s also kind of very specific for numbers so i think it might be better as an addon that can interpolate an ofParameter

ah that’s true, yes. i think this could be solved with template specialization so that those functions are only defined for parameter types which could be interpolated (float, int, ofVec3f, ofVec2f, ofPoint, etc).
in any case, i will put it up as an addon soon.

yes, in any case, ofParameter is more a data container, any behaviour should go out of the class