24

I would like to refresh the dat.gui menu with new values. I have loaded a model and display in folder the name of the objects inside a gui folder.
How can I display the new object name when I reload a other model ?
Or it's possible to reset/clear the gui. enter image description here

Adi Shavit
  • 16,743
  • 5
  • 67
  • 137
user2244365
  • 577
  • 2
  • 5
  • 10

9 Answers9

30

Basically, you have to set the controllers to "listen" for input when you add them, for example,

gui = new dat.GUI();
var guiX = gui.add( parameters, 'x' ).min(0).max(200).listen();

For documentation, see:

http://workshop.chromeexperiments.com/examples/gui/#9--Updating-the-Display-Automatically

For an example of this in Three.js, see:

http://stemkoski.github.io/Three.js/GUI-Controller.html

Stemkoski
  • 8,936
  • 3
  • 47
  • 61
  • It's doesn't wok, because first time when I load a model I have a folder with some names like : folder.add(name1, true); folder.add (name2, true); ... And when I load a new model the name changes. So I would like to change the name in folder or reset the gui. – user2244365 Apr 24 '13 at 09:14
  • Finally I found a solution with the gui add prototype of Andreas Köberle which remove folders – user2244365 Apr 24 '13 at 11:57
  • It seems the listen does not work anymore. I am trying to listen to a SelectController, and I get a warning when I load my page `'webkitRequestAnimationFrame' is vendor-specific. Please use the standard 'requestAnimationFrame' instead.` dat.gui.js:2841 I am using Chrome version 40.0.2214.115 – Ozair Kafray Mar 05 '15 at 05:14
  • I don't know if it's officially supported, but setting the controller's `options` seems to work. Example : http://stackoverflow.com/a/41382243/1431042 – Me.Name Dec 29 '16 at 15:07
  • The ```.listen()``` was what I was looking for. This updates dat.gui when the values are changed outside of dat.gui. Thank you Lee Stemkoski. – Marty McGee Nov 23 '20 at 17:22
  • WARNING! Bugs ahead! I have tried using ".listen()" for my application. It works well for updates, but it introduces numerous bugs! In my case, it was being unable to manually change numbers on sliders. These bugs are documented as issues in dat.gui Github repo. – Hafplo Mar 16 '21 at 09:28
17

Echt Einfach's solution didn't work for me, and Stemkoski's one is a bit wide. I finally made it with the updateDisplay function:

for (var i in gui.__controllers) {
    gui.__controllers[i].updateDisplay();
}

http://workshop.chromeexperiments.com/examples/gui/#10--Updating-the-Display-Manually

Note that if you have the values in some folder folder1 the call is like this:

for (var i = 0; i < this.gui.__folders.folder1.__controllers.length; i++) {
    this.gui.__folders.folder1.controllers[i].updateDisplay();
}

If you do not want to hard-code folder1, or simply want to update all folders, you can proceed as follows:

for (var i = 0; i < Object.keys(gui.__folders).length; i++) {
    var key = Object.keys(gui.__folders)[i];
    for (var j = 0; j < gui.__folders[key].__controllers.length; j++ )
    {
        gui.__folders[key].__controllers[j].updateDisplay();
    }
}
macrocosme
  • 473
  • 7
  • 24
jmmut
  • 884
  • 9
  • 19
  • Better solution than listener. Listening was building up in memory and causing unnecessary, intensive processor work. Thank you! – atom Apr 22 '22 at 14:09
4

Wrote a function to update dat.gui dropdowns with a new set of values:

function updateDatDropdown(target, list){   
    innerHTMLStr = "";
    if(list.constructor.name == 'Array'){
        for(var i=0; i<list.length; i++){
            var str = "<option value='" + list[i] + "'>" + list[i] + "</option>";
            innerHTMLStr += str;        
        }
    }

    if(list.constructor.name == 'Object'){
        for(var key in list){
            var str = "<option value='" + list[key] + "'>" + key + "</option>";
            innerHTMLStr += str;
        }
    }
    if (innerHTMLStr != "") target.domElement.children[0].innerHTML = innerHTMLStr;
}

Usage:

myDropdown = gui.add(MyObject, 'myVariable', ['one','two','three']);
updateDatDropdown(myDropdown , ['A','B','C']);

// Also accepts named values

updateDatDropdown(myDropdown , {'A':1,'B':2,'C':3});
3

Lee Stemkoski's and Echt Einfach's solutions use the .listen() method on a selected controller in the GUI.

jmmut's solution ,using .updateDisplay(), loops through ALL of the controllers in the GUI

It strikes me that both these solution types are EXPENSIVE if you only want to manually update the value of a single controller at a particular time.

You can avoid this by using the method .updateDisplay() for a SINGLE controller.

One way to do this is if you know beforehand the index[i] of the single controller. But this is rather fiddly to implement.

A better way is to reference the particular controller by name

// AT INITIALISATION TIME
gui1 = new dat.GUI();
Gparameters = { x: 0, y: 0, z: 0}
var gui1_X = gui1.add( Gparameters, 'x' ).min(0).max(200); // note no need to use the method .listen()

// AT RUN TIME
Gparameters.x++;
gui1_X.updateDisplay()  

Note: I have not included the extra code required to make this work with controllers inside folders. You can get this from the other answers.

steveOw
  • 879
  • 12
  • 41
3

It's easy when I have read the source code of dat.gui:

https://github.com/dataarts/dat.gui/blob/master/src/dat/controllers/Controller.js#L36

As you see, this.object = object, this is a controller you add, and object is what you need to change. Here is example code:

var gui = new dat.GUI();

// init a controller
var controller = gui.add(object, 'property');

// update a controller
controller.object = newObject;
徐乾伟
  • 31
  • 1
2

My answer does not reflect your question but will be helpful for others that programmatically change values within the 3d scene and need to update the GUI controls.

When you declare:

    var cubeX = folder1.add( parameters, 'x' ).min(-100).max(100).step(1).listen();

you have declared parameters beforehand, e.g.

parameters = {
    x: 0, y: 0, z: 0
}

Now you can listen to the key events or the appropriate event and change the values in the GUI like that:

window.addEventListener('keydown', function(event) {
    if(event.keyCode == 88) { // x pressed
        parameters.x++; // GUI value changed
        cube.scale.x = parameters.x; // 3d object changed
    }
}
Avatar
  • 14,622
  • 9
  • 119
  • 198
1

listen has a bug associated with it, if you use dropdown menus. See here: https://code.google.com/p/dat-gui/issues/detail?id=59

Here's a short function to update all controllers by iterating through all folders.

function updateDisplay(gui) {
    for (var i in gui.__controllers) {
        gui.__controllers[i].updateDisplay();
    }
    for (var f in gui.__folders) {
        updateDisplay(gui.__folders[f]);
    }
}
thc
  • 9,527
  • 1
  • 24
  • 39
0

None of above answers worked for me. I simply recreated DAT GUI and it worked.

I will not recommend it but if nothing works and you don't wanna spend more time in this then simply delete current DAT GUI:

this.gui.destroy()

And then recreate DAT GUI with parameters.

Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
0

You have to update your controller with the updateDisplay() method

gui = new dat.GUI()
//edit values
gui.updateDisplay()

See the dat.GUI API documentation: updateDisplay

kappoo
  • 33
  • 5