View Full Version : Scale and distribute selected uv shells

10 October 2011, 08:48 PM
I am trying to do a script (mel) that scales selected uv shells and then distributes then between the most right and the most left selected uv shell.

The user would select all the uv's he/she want's to scale and re-distribute. The script would pop a dialog that asks for the U and the V scaling factor. When the user hit's enter the script would pick each shell and scale it. At the end it would distribute the selected shells evenly between the most left and the most right uv shell (prolly through bounding box calculations.

I've been searching the web and trying a bunch of things but it seems to be hard to even get the amount of selected uv shells into a list to walk through and scale them. I found a few hints that point out that the Maya API does have commands to get the number of uv shells selected. But nothing usable in mel or python.

Any help appreciated!



10 October 2011, 02:26 AM
Hey, yep I do this all the time. While I cant release all the company code really, I can work you through the process. Sorry, its all gonna be in Python though...

First we have a method GetShells(obj) which takes in either an entire object or a component or a list of components.

Step A:
Using a combination of and maya.cmds.polyListComponentConversion, I end up with the name of the object (e.g. pPlane1) and a flat list of UV indices. This step should be fairly straightforward to do.

Step B:
From the full object name, we use the API MFnMesh.getUvShellsIds to get an array. This array contains the UV shell number for each UV in a given UV set. For example, the array [ 0, 0, 0, 1, 1, 1, 1, 0 ] would represent an object where UVs 0, 1, 2 and 7 are connected together (UV shell number 0), and UVs 3 to 6 belong to shell number 1.

In short:
- Get the dagPath from the object name using MSelectionList and MDagPath
- Ah hell, ill just post some code for the next bit:

uvShellIDs = maya.OpenMaya.MIntArray()

sutil = maya.OpenMaya.MScriptUtil()
uint = sutil.asUintPtr()

myMesh.getUvShellsIds(uvShellIDs, uint)

finalList = list()

for z, shellID in enumerate(apiTools.ArrayIter(uvShellIDs)):
tempID = shellID

Now, the finalList stuff at the end may seem pretty stupid, which it IS, but I found maya to be a bit crashy without it in 2009. Perhaps this isn't a problem anymore...

Step 3 - Get list of UVs grouped by shell
Should be straightforward, just collect the relevant ids from your finalList based on Step1 results, and then group the UVs accordingly.

Cool thing about this method is that if your StepA is flexible enough, the user can just select objects or faces, or edges, or uvs, or uv shells, it doesnt really matter.

10 October 2011, 04:57 AM
If you wanted to do it all in MEL, i guess you could use polyListComponentConversion and iterate over your faces, converting to uvs as you go. Then start grouping the uvs together if multiple faces share the same UVs.

You should(?) end up with one group for each shell.

10 October 2011, 04:25 PM
Thanks dbsmith and sorry for my delay on getting back to you.

In fact I do have a problem with Python. Because I am not very fluent in Python :) But it might be a good exercise I guess. Maybe a bit heavy to start on Python. A very nice side effect of Python seems to be that we can use API calls.

I was trying to get it done using MEL, but it's a hell of a lot of work.

I am putting this on low priority for now but I will chew on it in between things and I might bother you again if that's ok.

Thanks again!


11 November 2011, 11:10 PM
I have created a UV script in Maya. Its called Ninja UV and you can get it on creative crash.
I have a tool that will layout selected shells either horizontally or vetically. If you cant get your code to work, you can look at the Ninja_UV script:

The way i get UV shells is to collect all the shells into an array and then when i need to access them i tokenize the array in a for loop. Might not be the most elegant way but it works :).

global proc string[] NinjaUV_CollectShells()
PolySelectConvert 4;
$Selection =`ls -sl -fl`;
string $UVs[] = `ls -sl -fl`;//base uv's
string $Test_UVs[] = `ls -sl -fl` ;
string $Shell[];
string $Shell_string;
string $Shell_array[];
for ($s = 0; $s < `size $UVs`; $s++)
$test_UV = stringArrayContains ($UVs[$s], $Test_UVs);// checks to see if the UV is in the array after removing shell
if ($test_UV == 1)
select -r $UVs[$s];
SelectUVShell ;
string $Shell[] = `ls -sl -fl`;//flattens uv selection
string $Shell_string = stringArrayToString ($Shell,",");//converts array to string
$new_UVs = stringArrayRemove ($Shell, $Test_UVs);//removes shells from base uvs
$Test_UVs = $new_UVs;//updates UV array to remove shell
stringArrayInsertAtIndex(0 , $Shell_array, $Shell_string);
}//end if
}//end for
return $Shell_array;//returns an array of strings that needs to be tokenized thru a for loop

string $Shells[] = NinjaUV_CollectShells();

for ($s = 0; $s < `size $Shells`; $s++)
string $Single_Shell[];
tokenize $Shells[$s] "," $Single_Shell;
select -r $Single_Shell;

CGTalk Moderation
11 November 2011, 11:10 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.