A better way to write this MEL script

Someone at work wanted to be able to find all the nodes with a certain name in the scene, say it had the string “ear” in the name but they couldn’t remember the whole name but had a million nodes to look through. So I made this little window, but I’m wondering if there is a more efficient way of writing it? I’m going to convert it to python next for learning purposes.


//node finder
//by Matt Murray 2011
// Merry Christmas Brian :P

window -t "Search" -w 250 -h 100 myWin;
	columnLayout -adj true;
		$bob = `textFieldGrp -l "Node Name:"`;
		button -l "Find" -c "findNode($bob)";

showWindow myWin;

proc findNode(string $myText)
{
	$nodes = `ls`;
	$bobName = `textFieldGrp -q -tx $myText`;
	for($n in $nodes)
	{
		$outPut = `match ($bobName + "") ($n+"")`;
		if($outPut != "")
		{
			print($n + "
");
			select -r $n;
		}
		
	}
	
}

There isn’t really anything I could find on google on how to do something like this in Maya so I just kind of pulled it out of you know where…:D: . If I wanted to put those objects returned into a list and then have the object get selected when i highlight the list, how might I go about doing that?

Add in a textScrollList to your layout:


window -t "Search" -w 250 -h 100 myWin;
    columnLayout -adj true;
        $bob = `textFieldGrp -l "Node Name:"`;
        button -l "Find" -c "findNode($bob)";
        textScrollList -allowMultiSelection on -height 145 -width 200 scrollListName;

and then add this to your code:

		
if($outPut != ""){
    print($n + "
");
    textScrollList -e -a $n scrollListName;
    select -r $n;
}

And that’ll give them a textScrollList that they’ll be able to select from. You’ll have to add another button to allow them to select all of their selected objects in the textScrollList, but that’s nbd. :slight_smile: HTH.

Awesome. Thanks for your help. The list is exactly what we decided we needed this morning when we played with it. I had one other question. would it be possible to make it refresh the list as you type in your string(like google :P)? I’m not sure how to tie an event to adding text into a textfield like that. Or is it even possible? If not in MEL maybe in Python?

The textFieldGrp has a flag that will fire a command when the text changes

http://toi.bk.tudelft.nl/maya/help/docs/Maya2009/en_US/Commands/textFieldGrp.html#flagforceChangeCommand

Also if you wanted to do away with the “Find” button you could have the item be selected every time the person clicks an item in the list using the -selectCommand in the textScrollList

http://toi.bk.tudelft.nl/maya/help/docs/Maya2009/en_US/Commands/textScrollList.html#flagselectCommand

Since your using “match” you could throw in a wild card as match is able to use regular expressions.

I’d also point out that if you are using mel you should be a little more explicit with your definitions for the data types that you are using.

Without those explicit definitions you can encounter odd bugs that become more difficult to track in more complex scripts so getting into the habit early is a good thing.
I know python does not do this but this is something thats easier to catch with debuggers etc that mel does not have.


//node finder
//by Matt Murray 2011
// Merry Christmas Brian :P

window -t "Search" -w 250 -h 100 myWin;
	columnLayout -adj true;
		string $bob = `textFieldGrp -l "Node Name:"`;
		button -l "Find" -c ("findNode " + $bob);
showWindow myWin;

proc findNode(string $myText)
{
	string $nodes[] = `ls`;
	string $bobName = `textFieldGrp -q -tx $myText`;
	for($n in $nodes)
	{
		string $outPut = `match ($bobName + "") ($n+"")`;
		if($outPut != "")
		{
			print($n + "
");
			select -r $n;
		}
		
	}
	
}

button -l “Find” -c ("findNode " + $bob);
// your version intrigued me as putting a string var inside the “” does not assign a value to it, it should complain but I guess its not wrapped so it works for some reason.

I’m also intrigued that you can find the proc as the window button command usually requires the proc findNode to be a global proc as proc is local to the script. Again must be a side effect of the Window not being wrapped in a global proc.

@ rhexter

When you say “add a wild card”, are you meaning the “*” symbol to the expression? And one other thing that was requested was to make the search optional to be case sensitive or not, would that work with the match method?

Here is the code up to date:


//node finder
//by Matt Murray 2011
//mattanimation@gmail.com
// 

if(`window -ex myMin`) deleteUI myWin;


window -t "Search" -w 250 -h 100 myWin;
    columnLayout -adj false;
    
            rowLayout;
		    optionMenu -l "Filter By:" filtersBox;
		        menuItem -l "All";
		        menuItem -l "Mesh";
		        menuItem -l "Lights";
		        menuItem -l "Containers";
		        menuItem -l "Cameras";
		        menuItem -l "Materials";
		        menuItem -l "Containers";
		        menuItem -l "Textures";
		        menuItem -l "Sets";
		        menuItem -l "Visible";
		        menuItem -l "Invisible";
		        menuItem -l "Templated";
		       
	    setParent..;

	    columnLayout -adj true;
		    textFieldGrp -l "Node Name:" -cc "findNode()" objName;
		    textScrollList -allowMultiSelection on -height 145 -width 200 -sc "selObjs()" objList;
		    
		   

showWindow myWin;

//end main


proc findNode()  //find the node
{

	//clear the list
    textScrollList -e -ra objList;
    
    //check the filter
    string $filt = `optionMenu -q -v filtersBox`;      
    
    switch($filt)
    {
        case "All":
        string $nodes[] = `ls`;
        break;
        
        case "Mesh":
        string $nodes[] = `ls -g`;
        break;
        
        case "Lights":
        string $nodes[] = `ls -lt`;
        break;
        
        case "Containers":
        string $nodes[] = `ls -con`;
        break;
        
        case "Cameras":
        string $nodes[] = `ls -ca`;
        break;
        
        case "Materials":
        string $nodes[] = `ls -mat`;
        break;
        
        case "Textures":
        string $nodes[] = `ls -tex`;
        break;
        
        case "Sets":
        string $nodes[] = `ls -set`;
        break;
        
        case "Visible":
        string $nodes[] = `ls -v`;
        break;
        
        case "Invisible":
        string $nodes[] = `ls -iv`;
        break;
        
        case "Templated":
        string $nodes[] = `ls -tm`;
        break;
    }    
    
	
	string $targetName = `textFieldGrp -q -tx objName`;
	string $n = "";
	
	//check each node in the scene
	for($n in $nodes)
	{
		//if it matchs name with the target string anywhere in the string then add it to the list
		string $outPut = `match ($targetName + "") ($n+"")`;
		if($outPut != "")
		{ 
		    textScrollList -e -a $n objList;
		}
		
	}
	
}

proc selObjs() //select the object when selected from the list
{
	$mySel = `textScrollList -q -si objList`;
	select -r $mySel;
}


This might be useful as a opening to the more regular things:
http://xyz2.net/mel/mel.094.htm

Yes regular expressions are capable of many things including expressing character case. Its a huge subject and can be quite head spinning, I’m no expert but I do try and butt heads with them on a regular basis to try and get it through my thick head. :wink:

I found this for the comparing string cases.
http://xyz2.net/mel/mel.079.htm

You can do something similar just using the outliner.
There is a text field just below the outliners menu bar. This field filters everything in the outliner.
So if you wanted to find all the nodes in the scene that contained the word ‘ear’ just type ‘ear’.
Clicking the icon to the left of the fiend resets the filter.

Keir

Wow I feel dumb, the whole reason I made that was cause that field doesn’t find things unless it has the exact name…or so I thought, oh well, I learned a lot.

Don’t feel dumb. I’ve met quite a few people who have WAY more experience in Maya than me that didn’t know about that feature. There’s also the command box at the top right hand corner, where you can choose “select by name” from the drop down and do the same thing. :wink:

Its good the functionality is there, but you found something to drive a need to try and script something.

Less pressure but try and finish the script(maybe narrow to a couple of common data types) if you can as you are learning a lot about scripting as well. Knowledge that will get you further in other areas that you actually need something custom. i.e. filtering data of a certain type with only specific game attributes could be worked into your custom version.

My comment on the regular expressions revolved around the fact that you are passing the search string from the UI and using it in a match statement so you can use (MAYA)regular expressions within the search field you provided.

[aA]pple[jJ]uice -> in the search stringwould consider

applejuice
Applejuice
AppleJuice
appleJuice

Thanks for the advice, I ended up just adding a check box to allow it to be case insensitive or not, and then use the tolower() method on the arguments if the box is checked. Since most people aren’t informed about how to use the regular expressions I think I might just leave it at that.