john
john

Reputation: 418

Maya Python: name not defined with floatSliderGrp

I'm trying to get a scale slider steup, and whenever I change the slider value, I'd like for the new value to be printed out:

    scaleSlider = cmds.floatSliderGrp(label='Curve Scale', 
                                  field=True, 
                                  minValue=0.0, 
                                  maxValue=2.0, 
                                  fieldMinValue=0.0, 
                                  fieldMaxValue=2.0, 
                                  value=1, 
                                  cc="print cmds.floatSliderGrp(scaleSlider, q=True, v=True)" )

This seems pretty simple, but I'm getting this error:

// Error: name 'scaleSlider' is not defined
# Traceback (most recent call last):
#   File "<maya console>", line 1, in <module>
# NameError: name 'scaleSlider' is not defined //

The error is not very descriptive, unfortunately. I'm having trouble tracking down what the issue might be. At first I thought it was self-referential, but the error would tell me if so, correct?

Upvotes: 0

Views: 1557

Answers (2)

theodox
theodox

Reputation: 12218

Your problem is in the cc argument. First, you've passed a statement not a function: you'd need to wrap the whole thing in a def or a lambda to work correctly. Second, you're passing it a string reference to scaleSlider, but at the time the callback is defined that variable doesn't exist. There are circumstances under which this code would work and others under which it won't (inside a function, for example, it will fail). Using string callback arguments is an invitation to these kinds of problems.

It's easier to do it like this:

w = cmds.window() 
c = cmds.columnLayout()
s = cmds.floatSliderGrp("example")

def callback(*_):
    print s, "=", cmds.floatSliderGrp(s, q=True, v=True)

cmds.floatSliderGrp(s, e=True, cc=callback)
cmds.showWindow(w)

Because callback is defined after cmds.floatSliderGrp("example") has executed, it knows the value of s (don't use single-letter variables in real code!) . Because cmds.floatSliderGrp(s, e=True, cc=callback) executes after that, it passes the version of the callback which knows the correct value of s to this particular float slider group. This example will work in the listener or wrapped inside a function because the scoping is consistent.

@AriGold's solution will also work, although lambdas can't be used in a loop -- if you tried to run his solution in a loop all of the callbacks may end up pointing at the last UI element because lambda's bind very late.

Lots more detail on the different ways to set up UI callbacks here

Upvotes: 1

Ari Gold
Ari Gold

Reputation: 1548

work with dict and lambda,

def get_ui_value(ui_id, ui_type):
    mcds = globals()["cmds"]
    method = getattr(mcds, ui_type)
    print method(ui_id, q=True, v=True)

ui_dict = {}
ui_dict["flt_slider_xy"] = cmds.floatSliderGrp(label='Curve Scale', 
                              field=True, 
                              minValue=0.0, 
                              maxValue=2.0, 
                              fieldMinValue=0.0, 
                              fieldMaxValue=2.0, 
                              value=1)
ui_dict["int_slider_xy"] = cmds.intSliderGrp(label='Curve Scale', 
                              field=True, 
                              minValue=0, 
                              maxValue=10, 
                              fieldMinValue=0, 
                              fieldMaxValue=2, 
                              value=1)
cmds.floatSliderGrp(ui_dict["flt_slider_xy"], e=True, cc= (lambda message:get_ui_value(ui_dict[flt_slider_xy], "floatSliderGrp")))
cmds.floatSliderGrp(ui_dict["int_slider_xy"], e=True, cc= (lambda message:get_ui_value(ui_dict[int_slider_xy], "intSliderGrp")))

Upvotes: 2

Related Questions