ofxDatGui: A New User Interface for OF


#21

SynchedParameter isn’t meant as a replacement - it actually uses ofParameter

It’s basically made of up of this

//pseudocode
struct SynchedParameter
{
  ofParameter<T> parameter;
  T value;

  void update()
  {
     if(value != parameter)
    {  
       parameter.set(parameter.getName(), value);
    }
  }
} 

The idea is that you can change value like you would any other float, int, bool, etc and on update it is compared to the ofParameter value and sets it if it changed.

That way I can use ofParameter and all of it’s features (OSC Sync, building from toString/fromString) but pass the Value to anything that needs a reference to it. (e.g. ofxImGui, ofxSimpleGuiToo)

There may some overhead as pretty much every SynchedParameter used is checked on update but it’s been ok so far.


#22

oh i see, isn’t there anyway to attach a callback to those gui libraries? that way you could set it to the sert method of a parameter directly instead of having to have an extra class to update


#23

Hello @braitsch,

thanks for this very good looking and well documented UI lib. Works very well too!

Best,
Vincent


#24

Right, they don’t have callbacks (at least in ImGui’s case). That’s the approach I prefer actually, where the GUI widget is able to directly change the data and I don’t have to have a callback.

But if I do want a callback, I can attach one to the ofParameter inside SynchedParameter


#25

Thanks, this makes sense although I think ofParameter could use some tweaks if the intention is for it to be used with other guis.

Specifically it seems like almost all ofParameter objects were designed to work exclusively with sliders as most of them (with the exception of bools & strings) require a min, max and default value.

This makes it difficult to integrate an ofParameter<ofColor> object with a say a ColorPicker component that doesn’t use a min or max value but instead just maps to the value of a single color.

There are other components where a min & max value doesn’t make sense such as in the case of a 2d-pad or button matrix.

It seems to me there should be an ofParameterRange object which could hold three ints, floats, colors or whatever and would act as the base class to anything that got fed to a group of sliders.

Then any ofParameter<T> object would be free to just store a single value or object that could be mapped to any component it got fed to.

Also why doesn’t ofAbstractParameter implement an addListener function? This makes it difficult to assign a generic listener function that multiple ofParameters can subscribe to.


#26

Also to anyone else interested in ofParameter integration with ofxDatGui I added an example this morning on the dev branch that demonstrates sharing three ofParameters with a gui and a separate group of sliders. I’m not super happy with the implementation yet as I haven’t figured out how to rewrite the ofxDatGuiSlider constructor to take a generic ofParameter object and bind an event handler to it so as to avoid having to write separate constructors for every data type.


#27

That’s actually not a bad place to be if this is the only place you are needing the type. Otherwise you are likely going to be using typeid somewhere else to figure it out.


#28

Well right now I have a unique listener in each constructor for the specific data type that’s passed in (currently just float and int). I’d ideally like to have just one generic listener function and one ofAbstractParameter reference inside the slider class that can map to any kind of ofParameter that’s passed in.


#29

Basically I want to get rid of mParamInt & mParamFloat and just have one mParam pointer to the ofParameter reference that is passed, but the problem is ofAbstractParameter doesn’t implement an addListener method so that currently requires me to declare type specific listener functions as well (onParamInt & onParamFloat).


#30

I think the current solution is probably ok though considering you would have to either solve it with something like ofAbstractDatGuiSlider or probe the type later in order to set it

Also, I think the current way makes it fairly explicit for the user to know what type they are working with. For instance, passing in ofColor to a slider wouldn’t work in the current setup (nor should it)


#31

This doesn’t work with ofEnableDepthTest(); enabled. Just letting you know but great job. I’m using this in my project now.


#32

@jvcleave Good point, that’s a solid argument for multiple constructors that specify the acceptable data types.

@nathanblanchard12 Thanks for letting me know. I just pushed up a patch on dev that disables depth test in the draw methods.


#33

@braitsch about min and max, they are there by deafult because it’s a very frequently used feature but you can totally ignore it if you don’t use it and just use set(name, value). in the future we might add other types of parameters like parameters that have a scale (linear log…) and we might separate the range if we find it’s useful but by now ignoring min/max is totally fine.

to solve the int/float problem you would usually template your slider and then typedef to int/float slders. you probably want to do that anyway to avoid ambiguities and precission problems.

also you shouldn’t disable depth testing inside the gui like that, depth testing will make 2d drawing fail but that’s just how opengl works, push/pop style won’t restore it to it’s original value anyway and changing it is kind of heavy so it’s better to let the user handle that.


#34

Thanks @arturo I removed disableDepthTest from the draw calls.[quote=“arturo, post:33, topic:20553”]
in the future we might add other types of parameters like parameters that have a scale (linear log…) and we might separate the range if we find it’s useful but by now ignoring min/max is totally fine.
[/quote]

I’d encourage this as ofParameter kind of feels like it was designed specifically for ofxGui. I think separating the range from the value would encourage other gui authors to support ofParameter as it would make it more generic and convenient to work with.


#35

Hi @braitsch !

This looks awesome ! Already played with it and looks VERY promising !

Not sure if here is the place … but i would love to see :

  • Scrollable canvas (sometime when you don’t have a lot of space for the GUI, to have it all inside a scrollable canvas it’s very usefull)
  • Load/Save from/to XML or JSON files would be a must (i’ve seen it already on the roadmap)

If we could help with something … we’ll be happy to collaborate.


#36

@eloi actually, i like that doesn’t have a save and load option (ofXml is flexibel enough to do your own version), but more binding options (and not only sliders) will be good.


#37

I’ve created a json settings addon that lets you do a few things that ofxJSON can’t by itself, like bind values to a gui library like ofxDatGui or ofxUI. I also like the idea of keeping your app settings separate, and not dependent on, which GUI library you’re using for a production app, though I definitely see the appeal in having the GUI save/load settings directly for less complex apps, or for quick prototyping.

Anyway, this may be helpful to you. There’s a demo in the example about how to bind go a GUI…let me know if you check it out & have any questions!

Cheers


#38

@braitsch Question here – perhaps just user error. I’m creating a gui like this, in setup():

    gui = new ofxDatGui( ofxDatGuiAnchor::TOP_LEFT );
    gui->addLabel("SOURCE IMAGE SELECTION");
    gui->addTextInput("NEW IMAGE(S)", "ENTER FULL DIRECTORY PATH");
    gui->addButton("IMPORT IMAGE(S)");
    gui->addBreak()->setHeight(10.0f);
    
    vector<string> options;
    options.push_back("GRASS");
    options.push_back("MARS");
    options.push_back("ETC...");
    gui->addDropdown("SELECT AN EXISTING SOURCE IMAGE", options);
    gui->getDropdown("SELECT AN EXISTING SOURCE IMAGE")->onDropdownEvent(this, &ofApp::onDropdownEvent);

Basically, I just copied from the dropdown example.

When the menu first appears, it looks fine:

I can click to select…

But when I select an item, a grey background remains – that is, unless I select the menu and then click on the top selected item again, then the grey background disappears, as expected. Am I supposed to be telling the gui to redraw itself or something? Here’s the grey background:

Thanks for the awesome addon!


#39

Hi, change your last line from this:

gui->getDropdown("SELECT AN EXISTING SOURCE IMAGE")->onDropdownEvent(this, &ofApp::onDropdownEvent);

to this:

gui->onDropdownEvent(this, &ofApp::onDropdownEvent);

When you add a dropdown (or any component for that matter) to a gui, the gui creates an internal event handler that it uses to redraw itself whenever the component changes. Assigning an event handler directly to the component as you were doing overwrites the one the gui created which is why it wasn’t redrawing correctly.


#40

Hi @braitsch !

Is it possible to display the elements on a ofxDatGui in an horizontal layout scheme ? (i’m sure there is a proper way for naming this … sorry ;P)
I would love to be able to have some ofxDatGuiComponents arranged horizontally, not vertically …