Maya - Doing something to a control long after script execution

import re
import pymel.core as pm
path = pm.control("string_name_of_control", query=True, fullPathName=True )
ack = re.findall("[^|]+$", path)[0] # Gets the control name
ack = pm.PyNode(ack) # Convert to node
print ack.getValue()
# MayaNodeError: Maya Node does not exist (or is not unique):: u'string_name_of_control' # 

I have a problem where I need to alter something of a UI control after a script has been executed. Passing variables between scripts is in this case not possible. I have assigned a string name to the control and assigned it to a variable. And so far, so good. I can fetch the name of the control without any problems.

But as soon as I turn the name of this control into a node using pm.PyNode(), followed by the getValue() command I get this Maya Node Error. Why?

Best example of replicating this problem is to say, creating a window with one script and then having another script query a control in said window.

EDIT: The name “ack” is a reference to the movie Mars Attacks, where the aliens continously say “ack ack ack” :slight_smile:

string_name_of_control not being unique is probably the issue. Why don’t you want to use the long path name?

[QUOTE=Theodox;28229]string_name_of_control not being unique is probably the issue. Why don’t you want to use the long path name?[/QUOTE]
Didn’t think it would make a difference as I get exactly the same error using that. :frowning:

You can’t create a functools.partial which does the job using the scope when you kick off the script and then executeDeferred when you’re done?

[QUOTE=Theodox;28231]You can’t create a functools.partial which does the job using the scope when you kick off the script and then executeDeferred when you’re done?[/QUOTE]
I do not follow - elaborate.

if I needed a script to query the value of a GUI widget, and that script was completely separate to the GUI, then I would probably use optionVars to store the GUI values. Sort of like using global variables that persist in the userPrefs.

[QUOTE=Nightshade;28228]

import re
import pymel.core as pm
path = pm.control("string_name_of_control", query=True, fullPathName=True )
ack = re.findall("[^|]+$", path)[0] # Gets the control name
ack = pm.PyNode(ack) # Convert to node
print ack.getValue()
# MayaNodeError: Maya Node does not exist (or is not unique):: u'string_name_of_control' # 

I have a problem where I need to alter something of a UI control after a script has been executed. Passing variables between scripts is in this case not possible. I have assigned a string name to the control and assigned it to a variable. And so far, so good. I can fetch the name of the control without any problems.

But as soon as I turn the name of this control into a node using pm.PyNode(), followed by the getValue() command I get this Maya Node Error. Why?

Best example of replicating this problem is to say, creating a window with one script and then having another script query a control in said window.

EDIT: The name “ack” is a reference to the movie Mars Attacks, where the aliens continously say “ack ack ack” :)[/QUOTE]

So the problem you’ve got, is that you’re trying to wrap your UI object in a PyNode. The PyMel UI objects aren’t PyNodes, they’re PyUI.
Instead try something like this:


with pm.ui.Window('some_window', create=True) as win:
    pass

    
import re
import pymel.core as pm
path = pm.control("some_window", query=True, fullPathName=True )
ack = re.findall("[^|]+$", path)[0] # Gets the control name
ack = pm.ui.PyUI(ack) # Convert to node
print ack.getTitle()

Though the whole regex thing should be avoidable, if you’ve got the valid short name, you should just be good to go.
I use this one a lot for grabbing the main window.


ui_object = pm.ui.PyUI('some_window')
main_window = pm.ui.PyUI('MayaWindow')

Solid answers guys!
I ended up using pm.ui.PyUI. The names doesn’t have to be stored anywhere and I can get rid of the regex.
Thank you!

@nightshade: The idea would be to create an object that knows the gui widget when you’re in a scope that has that information, then pass that along to your working function and have it fire when the function completes: basically its just a callback. By packing it up into a functools.partial object you can remember the gui you care about and just say ‘update that’ from other functions without polluting those other functions with detailed knowledge of the gui:



from functools import partial

def object_maker(_, callback = None):
    # the _ is there to ignore the 'False' that always comes from button clicks...
    new_cube, new_shape = cmds.polyCube()
    if callback is not None:
        callback(new_cube)
        

def callback_window():
    w = cmds.window()
    c = cmds.columnLayout()
    t = cmds.nameField()
    
    # this captures the name of 't' when it's defined, you don't need to pass it on
    def update_me( obj):
        cmds.nameField(t, e=True, o = obj)
        
    # this captures the version of update_me which includes 't'.
    action = partial(object_maker, callback = update_me)
    b = cmds.button(command = partial(object_maker, callback=update_me))
    
    cmds.nameField(t, e=True, o='persp')
    cmds.showWindow(w)
    
callback_window()