PDA

View Full Version : MEL Slider - that hides/unhides child objects of a group


brfuk
06-14-2007, 03:25 PM
Hi. First request on cgtalk. :)

I'm working on some simple character animation. Kind of south park esque in style.
One thing that I'm finding very tiresome is constantly keying the visibility of various elements of the characters.

I"m interested in easing workflow in any way I can and I'm interesting in using MEL to do so. But I'm stumped as to how to utilise my limited coding knowledge on this one. Especially with a lack of mel/maya experience.

Here's my idea : I have certain groups in my characters hierarchy which contain many objects. Say a mouth shapes group. What I think would be very handy, would be a button which say could sit on the shelf. When clicked it examines the 'mouths' group and creates a list of the elements. Then is brings up a slider which when changed simply goes through the elements of the group. Selecting & unhiding the current one and hiding all the others. Then you can simply hit S to keyframe the choice.

This seems very flexible to me. Does anyone know how easy this is to do or can point me in the right direction? Maybe it's already been done (I've been looking but it's quite an obtuse little script to describe).

Thanks

goleafsgo
06-14-2007, 04:27 PM
Here is what steps you will have to learn (from a very high level):


1. Get the objects you want to work on...from a group or maybe a naming convention you use...

2. Create the window. You will probably want to use an intSliderGrp for your control. You can set how many "steps" there are on the slider by using the minValu/maxValue flags. You'll want to set this to how many objects that you have to work on.

3. Possibly do some initialization. Maybe you want to do an initial pass to make sure that there is only one of the objects currently visible...

4. Attach a callback command to the intSliderGrp's -dragCommand. The slider also has a -changedCommand but that only executes once you let go of the slider, and you probabaly want to see the changes while you are dragging.

5. In your callback you have to ask the intSliderGrp what is the current step it's on and then loop though all of the objects and set their visibility attribute to false...all of them except the one from the curret step.


That's about it. Here is some code to get you started...


global proc myDragCallback(string $intSliderName)
{
if (`intSliderGrp -query -exists $intSliderName`)
{
int $currentStep = `intSliderGrp -query -value $intSliderName`;
print ("You are on step = " + $currentStep + "\n");
}
}

global proc hideUnhideUI()
{
if (`window -query -exists MyHideUnhideUI`) {
deleteUI MyHideUnhideUI;
}

string $selection[] = `ls -sl`;
int $numberOfObjects = `size $selection`;

string $nameOfIntSlider;

window MyHideUnhideUI;
columnLayout;
$nameOfIntSlider = `intSliderGrp -label "My Label" -minValue 1 -maxValue $numberOfObjects`;

string $callback = "myDragCallback " + $nameOfIntSlider;
intSliderGrp -edit -dragCommand $callback $nameOfIntSlider;
showWindow;
}

brfuk
06-14-2007, 04:39 PM
Many many thanks Goleafsgo!

This is a very useful start. I'll see where I can take it.

goleafsgo
06-14-2007, 06:22 PM
No problem...let us know what you come up with.

brfuk
06-14-2007, 07:26 PM
I'm a little stuck at the moment. I think the issue is that i have to get the object list (an array of strings) & the total number of obects into the callback procedurde.

The trouble I'm having (I think) is correctly defining the callback string which is passed during the intSliderGrp.

The code below gives the following error when the slider is dragged :

// Error: myDragCallback(MyHideUnhideUI|columnLayout53|intSliderGrp1,9, $selection[] ); //
// Error: Invalid use of Maya object "MyHideUnhideUI|columnLayout53|intSliderGrp1". //


I hope this is down to my inexperience with MEL. Coding isn't my forte :)



global proc myDragCallback(string $intSliderName, int $numObjects, string $objectsToHide[])
{
if (`intSliderGrp -query -exists $intSliderName`)
{
int $currentStep = `intSliderGrp -query -value $intSliderName`;
print ("You are on step = " + $currentStep + "\n");

for ($i=0; $i < $numObjects; ++$i) {
setAttr ($objectsToHide[$i] + ".visibility") off;
}
setAttr ($objectsToHide[$currentStep] + ".visibility") on;
}
}

global proc hideUnhideUI()
{
if (`window -query -exists MyHideUnhideUI`) {
deleteUI MyHideUnhideUI;
}

string $selection[] = `ls -sl`;


int $numberOfObjects = `size $selection`;

print("----------HIDE - UNHIDE---------- \n");
print("You selected : \n");
print($selection);

// Hide All
for ($i=0; $i < $numberOfObjects; ++$i) {
setAttr ($selection[$i] + ".visibility") off;
}

setAttr ($selection[0] + ".visibility") on;


string $nameOfIntSlider;

window MyHideUnhideUI;

columnLayout;

$nameOfIntSlider = `intSliderGrp -label "Selection" -minValue 1 -maxValue $numberOfObjects`;

//string $callback = "myDragCallback( "+ $nameOfIntSlider + "," + $numberOfObjects + ", $selection)";
string $callback = "myDragCallback(" + $nameOfIntSlider + "," + $numberOfObjects + ", $selection[] );";

intSliderGrp
-edit
-dragCommand
$callback
$nameOfIntSlider;



showWindow;
}

goleafsgo
06-15-2007, 12:45 AM
I'm not in front of Maya right now but I think you're missing a quote in your command string. I think the part that's like this:

$numberOfObjects + ", $selection[] );"


should have extra quotes like this:

$numberOfObjects + ", " + $selection + ");"


i.e. your selection variable should not be inside the quotes...and once you do that you shouldn't need the "[]" part. Hope that helps.

brfuk
06-15-2007, 09:57 AM
Really appreciating your help goleafsgo! Sadly I already tried this. Passing this array through the callback string seems to be causing me problems.
I had the code as you have it above but I get this...



string $callback = "myDragCallback(" + $nameOfIntSlider + "," + $numberOfObjects + "," + $selection + ");";


// Error: string $callback = "myDragCallback(" + $nameOfIntSlider + "," + $numberOfObjects + "," + $selection + ");"; //
// Error: Illegal operation "+" on data of type string[]. //

If I add [] to the array variable I get a syntax error :(

Is MEL actually capable of passing an entire array like this?

brfuk
06-15-2007, 02:22 PM
This seems to be working. Possibly not that efficient and a bit hacked. But if you select some objects, the slider lets you cycle through them, only showing the currently one on the slider and hitting S sets all the keyable attributes. Which in this case is visibility.




global proc myDragCallback(int $numObjects, string $objectsToHide[])
{
global string $nameOfIntSlider;
if (`intSliderGrp -query -exists $nameOfIntSlider`)
{
int $currentStep = `intSliderGrp -query -value $nameOfIntSlider`;
for ($i=0; $i <= $numObjects; ++$i) {
setAttr ($objectsToHide[$i] + ".visibility") off;
}
print($objectsToHide[$currentStep] + " selected \n");
setAttr ($objectsToHide[$currentStep] + ".visibility") on;
}
}

global proc hideUnhideUI()
{
if (`window -query -exists MyHideUnhideUI`) {
deleteUI MyHideUnhideUI;
}

string $selection[] = `ls -sl`;

int $numberOfObjects = `size $selection`;
$numberOfObjects--;
print("----------HIDE - UNHIDE---------- \n");
print("You selected : \n");
print($selection);

// Hide All
for ($i=0; $i <= $numberOfObjects; ++$i) {
setAttr ($selection[$i] + ".visibility") off;
}

setAttr ($selection[0] + ".visibility") on;


global string $nameOfIntSlider;

window MyHideUnhideUI;

columnLayout;

$nameOfIntSlider = `intSliderGrp -label "Selection" -minValue 0 -maxValue $numberOfObjects`;

string $callback = "myDragCallback(" + $numberOfObjects + ", (`ls -sl`));";

intSliderGrp
-edit
-dragCommand
$callback
$nameOfIntSlider;


showWindow;
}

goleafsgo
06-15-2007, 05:16 PM
I had a longer posting ready to go and before I hit Submit I got distracted and then closed my browser :sad:


If you really need to send an array to a UI callback in a string like that then you have to recreate it. Meaning you would have to loop through the array and append all the piecees together with quotes around them and the whole thing wrapped in curly brackets.

Instead of doing that I think you should just write another proc which will return the string array of objects that should be operated on. The way you have it now with the "ls -sl" I only put in as an example...it really won't work because your objects aren't going to be selected because all but one will be invisible.

Once you have something that you can call to return the string array then you can call that from your UI creation proc to figure out what the size is and you can also call it from the callback proc in order to hide/unhide the objects. This way you don't actually have to pass the string array explicitly.

Or you can just use a global string array, fill it in in the UI creation proc, and then use it in the callback.

Does that make sense?

CGTalk Moderation
06-15-2007, 05:16 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.