PDA

View Full Version : first mel, first problems (undeclared variable)


CrustedInk
07-20-2008, 06:47 PM
Hey.
I just wrote my first "real" mel-script. Nothing big, it resets all selected Objects.
actually, it works. but i wanted an ui, with 3 checkboxes. 1 for every attribute (translate, rotate, scale). the idea was, that you can click on the button in the shelf, and the script resets everything. the ui pops up when you click with pressed ctrlon it. That works with some help of a friend. the next time you click on the button, the script should run with the last settings.

the probleme.. there some undeclared variable, but i don't know how to fix it.Maybe somebody could help me with this. my idea was, that you have to run the script for the first time with the ctrl+click, thats why i declared the variables in the if_clause.

if (keysPressed() == "Ctrl")
{
$cb_s2 = 0;
$cb_t2 = 0;
$cb_r2 = 0;

window -wh 200 256;
columnLayout;
checkBox -label "Translate" -value $cb_t2 -onc "$cb_t2 = 1" -ofc "$cb_t2 = 0";
checkBox -label "Rotate" -value $cb_r2 -onc "$cb_r2 = 1" -ofc "$cb_r2 = 0";
checkBox -label "Scale" -value $cb_s2 -onc "$cb_s2 = 1" -ofc "$cb_s2 = 0";
button -label "Reset 'em " -command "dr_resetObj_proc(`ls -sl`,$cb_t2,$cb_s2,$cb_r2)";
showWindow;
}
else
dr_resetObj_proc(`ls -sl`,$cb_t2,$cb_r2,$cb_s2);

global proc string keysPressed()
{
int $mods = `getModifiers`;
string $keys = "";
if (($mods / 1) % 2)
{
if ($keys == "") $keys += ("Shift");
else $keys += (" Shift");
}
if (($mods / 2) % 2)
{
if ($keys == "") $keys += ("CapsLock");
else $keys += (" CapsLock");
}
if (($mods / 4) % 2)
{
if ($keys == "") $keys += ("Ctrl");
else $keys += (" Ctrl");
}
if (($mods / 8) % 2)
{
if ($keys == "") $keys += ("Alt");
else $keys += (" Alt");
}
return $keys;
};

global proc dr_resetObj_proc(string $ctrl_reset[], string $cb_t2, string $cb_s2,string $cb_r2)
{

for($i=0;$i<`size $ctrl_reset`;$i++)
{
if ($cb_t2 == 1)
{
setAttr ($ctrl_reset[$i] + ".translateX") 0;
setAttr ($ctrl_reset[$i] + ".translateY") 0;
setAttr ($ctrl_reset[$i] + ".translateZ") 0;
}
if ($cb_s2 == 1)
{
setAttr ($ctrl_reset[$i] + ".scaleX") 1;
setAttr ($ctrl_reset[$i] + ".scaleY") 1;
setAttr ($ctrl_reset[$i] + ".scaleZ") 1;
}
if ($cb_r2 == 1)
{
setAttr ($ctrl_reset[$i] + ".rotateX") 0;
setAttr ($ctrl_reset[$i] + ".rotateY") 0;
setAttr ($ctrl_reset[$i] + ".rotateZ") 0;
}
}
};

francisvega
07-21-2008, 04:51 AM
if you declare $cb_s2, $cb_t2, $cb_r2 inside of if, you can't use them outside of if, because if "IF" is false the vars doesn't declare and you can't use them outside.

You must be declare outside like this:

// Declare first
int $cb_s2 = 0;
int $cb_t2 = 0;
int $cb_r2 = 0;

if (keysPressed() == "Ctrl")
{
window -wh 200 256;
columnLayout;
checkBox -label "Translate" -value $cb_t2 -onc "$cb_t2 = 1" -ofc "$cb_t2 = 0";
checkBox -label "Rotate" -value $cb_r2 -onc "$cb_r2 = 1" -ofc "$cb_r2 = 0";
checkBox -label "Scale" -value $cb_s2 -onc "$cb_s2 = 1" -ofc "$cb_s2 = 0";
button -label "Reset 'em " -command "dr_resetObj_proc(`ls -sl`,$cb_t2,$cb_s2,$cb_r2)";
showWindow;
}
else
dr_resetObj_proc(`ls -sl`,$cb_t2,$cb_r2,$cb_s2);

global proc string keysPressed()
{
int $mods = `getModifiers`;
string $keys = "";
if (($mods / 1) % 2)
{
if ($keys == "") $keys += ("Shift");
else $keys += (" Shift");
}
if (($mods / 2) % 2)
{
if ($keys == "") $keys += ("CapsLock");
else $keys += (" CapsLock");
}
if (($mods / 4) % 2)
{
if ($keys == "") $keys += ("Ctrl");
else $keys += (" Ctrl");
}
if (($mods / 8) % 2)
{
if ($keys == "") $keys += ("Alt");
else $keys += (" Alt");
}
return $keys;
};

global proc dr_resetObj_proc(string $ctrl_reset[], string $cb_t2, string $cb_s2,string $cb_r2)
{

for($i=0;$i<`size $ctrl_reset`;$i++)
{
if ($cb_t2 == 1)
{
setAttr ($ctrl_reset[$i] + ".translateX") 0;
setAttr ($ctrl_reset[$i] + ".translateY") 0;
setAttr ($ctrl_reset[$i] + ".translateZ") 0;
}
if ($cb_s2 == 1)
{
setAttr ($ctrl_reset[$i] + ".scaleX") 1;
setAttr ($ctrl_reset[$i] + ".scaleY") 1;
setAttr ($ctrl_reset[$i] + ".scaleZ") 1;
}
if ($cb_r2 == 1)
{
setAttr ($ctrl_reset[$i] + ".rotateX") 0;
setAttr ($ctrl_reset[$i] + ".rotateY") 0;
setAttr ($ctrl_reset[$i] + ".rotateZ") 0;
}
}
};

NaughtyNathan
07-21-2008, 09:15 AM
while Francis's solution is correct, his explanation falls slightly short so I feel it would be worthwhile to explain this a little more clearly...

Even if the if statement is TRUE you will still get undeclared variable errors, this is because those curly braces you use in your MEL code { } define the SCOPE of a block of code. ANY variable you declare inside the scope of { } is NOT visible outside of the scope unless they are already declared as global variables (you want to try to avoid using global variables wherever possible).

if you run that code on a hotkey or shelf button ALL three of those variables ($cb_s2, $cb_t2, $cb_r2) will be declared as global, simply because they are not being declared inside any { }.

as an aside, why are you bothering with the unwieldy "keysPressed" proc, when you could simply use if (($mods / 4) % 2) in the place of if (keysPressed() == "Ctrl")..?

:nathaN

CrustedInk
07-21-2008, 12:41 PM
ok thanks for the explanation :)
but i tried all ready the solution from francis. the problem is, the script works only with the ctrl+click, otherwise all variables are 0, because of the declaration at the begin of the script. my aim is, that you must only click the first time with ctrl, define which attributes you want to reset (e.g. translae = 1, rotate = 1, scale = 0) and then you can just click with the left button on the shelf icon and maya will use the last settings --> resets translate and rotate.
so, if i get i right, i have to use global variables or is there an other solution ??

and i will work on the keypressed proc. this was not from me. i got a from a friend.

NaughtyNathan
07-21-2008, 03:05 PM
here you go, this is the complete solution, just paste this onto a shelf button:


// Declare first
global int $gcb_s2;
global int $gcb_t2;
global int $gcb_r2;

if ((`getModifiers` / 4) % 2)
{
window -wh 200 256;
columnLayout;
checkBox -label "Translate" -value $gcb_t2 -cc "$gcb_t2 = #1";
checkBox -label "Rotate" -value $gcb_r2 -cc "$gcb_r2 = #1";
checkBox -label "Scale" -value $gcb_s2 -cc "$gcb_s2 = #1";
button -label "Reset 'em " -command "dr_resetObj_proc(`ls -sl`,$gcb_t2,$gcb_s2,$gcb_r2)";
showWindow;
}
else dr_resetObj_proc(`ls -sl`,$gcb_t2,$gcb_r2,$gcb_s2);

global proc dr_resetObj_proc(string $ctrl_reset[],int $cb_t2,int $cb_s2,int $cb_r2)
{
for($obj in $ctrl_reset)
{
if ($cb_t2 == 1) setAttr ($obj + ".translate") 0 0 0;
if ($cb_s2 == 1) setAttr ($obj + ".scale") 1 1 1;
if ($cb_r2 == 1) setAttr ($obj + ".rotate") 0 0 0;
}
}

(damn stupid crappy cgtalk code formatting..)

I've trimmed it down considerably, taking out most of the redundant junk... of course this could be optimized even further, and this example still uses things I'd never recommend you do in practice (global vars, defining global procs on a shelf button, etc..), but it should illustrate what was wrong with the original version. try to look through both the original and this version and figure out what's changed and why... I quite like this idea of ctrl-clicking shelf buttons and may evenb steal the idea for my own use :D ;) .... any further questions about this just ask!

:nathaN

CrustedInk
07-22-2008, 12:39 AM
a great :) it works.... thanks. and the code is so short... i am impressed. thanks. there are some improvements, i never though off, like the setAttr-part.
i think, i have to learn the commands with the flags..or look them up^^

the only thing, i don't unterstand is the "#1" .what does it ?

NaughtyNathan
07-22-2008, 09:20 AM
If you ever want to pass the value of a control into a command (which, let's face it, is 99% of the time) rather than have the control query itself you can reference it's value by using the #1 syntax. e.g:

checkBox -cc "print #1";

will print 0 or 1 (off or on) whenever the checkbox is changed... if you have a "grp" control with more than one control, you can use #2, #3, #4, etc.. to reference the appropriate control. e.g:

checkBoxGrp -ncb 3 -cc "print #1;print #2;print #3";

this works for almost all controls that have a value, int/float fields, sliders, checkboxes, text fields, etc..

:nathaN

Rupesh1122
07-23-2008, 05:56 AM
Great,
It's very helpful for animator

CrustedInk
07-29-2008, 12:33 AM
yes, thanks again nathan.
this realy helps me..and i could allready use my new knowledge for the last scripts.

and rupesh, a fellow student wanted this script for a better worklow at animation (like resetting the gui or character)... so.. great somebody else could use this :)

CGTalk Moderation
07-29-2008, 12:33 AM
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.