[Mel] Various and basic questions

Well, I have posted the same question on Polycount, but i figured out it might be more efficient to ask here with you guys ! :wink:

Since a few hours (maybe more) I’m trying to learn and make a custom tool for Maya and my workflow.
I have already programmed in C++ in the past, so the Mel language is not so hard to understand for me.

The hard part is to find the name of the various function inside maya, but even with that, I still have some problems:


Currently, I’m trying to applying a shader on an object selected in the scene.
When my script start, I create my shaders like this :

    global string $shaderRetopo; //red retopo shader
    global string $shaderHighpoly; //blue high poly shader

    //setup shaders
    $shaderRetopo   =    `shadingNode -asShader -shared -name "sh_Retopo" phong`;
    setAttr($shaderRetopo+".transparency")     -type double3 0.25 0.25 0.25; //must be done just after, or we need to reselect the shader before
    setAttr($shaderRetopo+".color")     -type double3 0.5 0.0 0.0;
    
    $shaderHighpoly =    `shadingNode -asShader -shared -name "sh_Highpoly" lambert`;
    setAttr($shaderHighpoly+".transparency")     -type double3 0.25 0.25 0.25;
    setAttr($shaderHighpoly+".color")     -type double3 0.4 0.5 0.8;

This is the easiest part for me.
Now, even if I try to understand as much I can, I can’t figure out how to select the last object in my current selection and apply the shader on it.

I have tested this :

global proc froApplyShader(int $input)
{
    global string $shaderRetopo;
    global string $shaderHighpoly;
    string $temp = "";
    
    if($input == 1) //apply red shader
    {
        $temp = $shaderRetopo+"SG";
    }
    else //apply blue shader
    {
        $temp = $shaderHighpoly+"SG";
    }
    
    sets -e -forceElement $temp;
}
But in maya a get an error, it looks like my variable are empty, even if the shaders are well created in the hypershade.


----
My second attemp is to change the current component mode on the last selected object, i have tried this :
global proc froChangeSelectMode(int $input)
{
    string $select[] = `ls -sl`;
    int $mxSel = `size($select)`;

    //select -cl; //clear selection
    
    //change mode on the last selected object
    if($input == 4)
        doMenuComponentSelection($select[$mxSel], "meshComponents");
    else if ($input == 3)
        doMenuComponentSelection($select[$mxSel], "facet");
    else if ($input == 2)
        doMenuComponentSelection($select[$mxSel], "edge");
    else if ($input == 1)
        doMenuComponentSelection($select[$mxSel], "vertex");
    else
        select -r $select[$mxSel]; //classic select, object mode
}

But it’s not working and I can’t get why.

Any help will be greatly rewarded with my eternal gratitude!

This is the first time that I made a script in Mel, so it would be logical if some basic concept are ousted ! I have only learned by looking into other scripts.

Try this out:


global proc froApplyShader(int $input, string $selectedObjects[])
{
    global string $shaderRetopo;
    global string $shaderHighpoly;
    string $temp = "";
    
    if($input == 1) //apply red shader
    {
        $temp = $shaderRetopo+"SG";
    }
    else //apply blue shader
    {
        $temp = $shaderHighpoly+"SG";
    }
    
    sets -edit -forceElement $temp $selectedObjects;
}

In most cases it is better to pass in the objects you want work with directly, rather than rely on having the right things selected at the right time.

I’d highly suggest using python and maya.cmds (and then pymel) rather than MEL. It will make, well, everything easier.

Hmmm, I have read a lot of time that it’s easier in Python, but can I ask why ?
It’s faster ? Or it’s just the language which is easier ?


Otherwise, I have made some advancement. I have fixed my shader problem with :

	//setup shaders
	$shaderRetopo   =	`shadingNode -asShader -shared -name "sh_Retopo" phong`;
	string $shaderRetopoSG   = `sets -renderable true -noSurfaceShader true -empty -n ($shaderRetopo+"SG")`;
	setAttr($shaderRetopo+".transparency") 	-type double3 0.25 0.25 0.25; //must be done just after, or we need to reselect the shader before
	setAttr($shaderRetopo+".color") 	-type double3 0.5 0.0 0.0;
	
	$shaderHighpoly =	`shadingNode -asShader -shared -name "sh_Highpoly" lambert`;
	string $shaderHighpolySG   = `sets -renderable true -noSurfaceShader true -empty -n ($shaderHighpoly+"SG")`;
	setAttr($shaderHighpoly+".transparency") 	-type double3 0.25 0.25 0.25;
	setAttr($shaderHighpoly+".color") 	-type double3 0.4 0.5 0.8;
	select -cl; //clear selection

and then :

//apply one of the two shaders to the selected object
global proc froApplyShader(int $input)
{
	global string $shaderRetopo;
	global string $shaderHighpoly;
	
	string $sel[] = `ls -sl -fl`;
	
	if($input == 1) //apply red shader
		hyperShade -assign sh_Retopo;
	else //apply blue shader
		hyperShade -assign sh_Highpoly;
	
	select -r $sel[`size $sel` -1]; //reselect object
}

It works very well now ! :slight_smile:


For the selection problem, well, the problem is that if I change my component mode just after I have changed my component mode without selecting nothing I was getting an error. I’m still trying to understand better this problem, but currently I have fixed this with :

global proc froChangeSelectMode(int $input)
{
	string $select[] = `ls -sl -fl`;
	int $mxSel = `size($select)`;
	setSelectMode components Components;
	
	//change mode on the last selected object
	if( $mxSel-1 >= 0 )
	{
		select -cl; //clear selection
		if($input == 4)
			doMenuComponentSelection($select[$mxSel-1], "meshComponents");
		else if ($input == 3)
			doMenuComponentSelection($select[$mxSel-1], "facet");
		else if ($input == 2)
			doMenuComponentSelection($select[$mxSel-1], "edge");
		else if ($input == 1)
			doMenuComponentSelection($select[$mxSel-1], "vertex");
		else
		{	
			select -cl; //clear selection
			selectMode -object;
		}
	}
	else
	{
		//"selecType"
		//Attributes :
		/*
		-subdivMeshPoint(-smp) 	boolean
		-subdivMeshUVs(-smu)	boolean
		-subdivMeshEdge(-sme) 	boolean
		-subdivMeshFace(-smf)	boolean	
		-polymeshUV(-puv)		boolean
		-polymeshVertex(-pv) 	boolean
		-polymeshEdge(-pe) 		boolean
		-polymeshFace(-pf)		boolean
		*/
		
		select -cl; //clear selection
		if($input == 4)
			selectMode -object;
		else if ($input == 3)
			selectType -smp 0 -sme 0 -smf 1 -smu 0 -pv 0 -pe 0 -pf 1 -puv 0;
		else if ($input == 2)
			selectType -smp 0 -sme 1 -smf 0 -smu 0 -pv 0 -pe 1 -pf 0 -puv 0;
		else if ($input == 1)
			selectType -smp 1 -sme 0 -smf 0 -smu 0 -pv 1 -pe 0 -pf 0 -puv 0;
		else
		{
			selectMode -r -object;
		}
	}
}

Not very nice and clean, I guess it’s my list of the selected thing which is not well done, I think I must limit this this to the object only and don’t allow the components selected (or not).


I have also an other question :
I know how to duplicate a vertex with a custom mel function. What I would like is to put an hotkey of this function on the middle mouse click.
So if use the left click, I will more the vertex (with the tweak mode) and if use the middle click i will duplicate it.
On the paper it’s simple, what I don’t know is how to put this hotkey on the mouse, I don’t have founded anything related to the mouse in the maya hotkey editor.

Alos, I’m wondering on how to change the hotkey by a mel command rather be obliged to do it manually.

I hope my question is enough clear ! :wink:

I have also an other question :
I know how to duplicate a vertex with a custom mel function. What I would like is to put an hotkey of this function on the middle mouse click.
So if use the left click, I will more the vertex (with the tweak mode) and if use the middle click i will duplicate it.
On the paper it’s simple, what I don’t know is how to put this hotkey on the mouse, I don’t have founded anything related to the mouse in the maya hotkey editor.
Alos, I’m wondering on how to change the hotkey by a mel command rather be obliged to do it manually.

hotkey is a documented command

You can substitute the mouse functionality of a popupMenu to act like a hotkey:
adding the script as cly_popUpKillsPopUPTemplate.mel
add the line

cly_popUpKillsPopUPTemplate;

to your userSetup.mel for building on every startup.
for a shift LMB hotkey:

// cly_popUpKillsPopUPTemplate.mel v0.1a 2011
// Roger Klado was here cuz no one else would do it fer me
// executes a command with a shift left mouse click action acting like a simple hotkey instead of a popupMenu UI
global proc cly_popUpKillsPopUPTemplate()
{
	if( `popupMenu -exists cly_popUpKillsPopUPTemplate` ) {
		deleteUI cly_popUpKillsPopUPTemplate;
	}
	popupMenu 
		-sh 1 	// shift modifier
		-button 1
		-mm 1 
		-p viewPanes 
		-pmc  ( "cly_dynMenuItemsB" )
	cly_popUpKillsPopUPTemplate;

}

// do something without building a menu
global proc cly_dynMenuItemsB()
{
print "goodbye cruel world I was supposed to be a ui not overloaded to work like a mouse clicked hotkey! 
";
}				// end

Although your popupMenu is only aware of which modifier keys and buttons were pushed you can still get the functionality of all the
keys the Hotkey command has access to as well with a little hack.
Since popupMenu command does not care if you are pressing additional buttons in addition to your popupMenu keys
( it does however care if they are buttons or the modifier keys it normally can use ) you can expose which keys
would not normally be “readable” by the popupMenu by querying optionVar values set by pressing said hotkeys in the postmenu command.
( this would require the hotkey order of keys to be pressed first and the command to be executed “on press”.)

The getModifiers command is helpful as well…
when giving yer ui additional mouse clicking functionality.

Thank you claydough ! It’s help me a lot (I think, I need to tets thaht) ! I was looking on draggerContext, but I can’t figure out how to use it correctly (very hard when you start with mel :D: ).

I don’t like bumping old threads, but I don’t like them without a solution neither (especially when I know the solution). It took me a bit of time to get what I wanted (and to understand Maya a bit better).

So in the end : the draggerContext command was indeed what I was looking for since I wanted to make a new “tool”. I also needed the “closestIntersection” method from the API to do a rayTrace on a surface and get a point in space.
I needed this method because I didn’t found a way to access the tweak selection mode and calling a custom function at the same time.

End result :

It was for a retopology tool, now available here : http://www.froyok.fr/blog/2013-06-maya-froretopo-3-4-a-fast-and-easy-retopology-script