View Full Version : Best way to find uv shell count based on selection?

11 November 2012, 05:07 PM
The user selects X amounts of UVs and wants to run a script on it.
That script however only works on one UV shell. So the script needs to be able to "detect" if the UVs selected are placed on more than one UV shell.
Is this even possible?

11 November 2012, 07:54 PM
As a naive approach you could convert the UV component selection into the UV shell. You can use the wrapper script "polySelectBorderShell 0;", this selects all UVs inside the same shell as your initial components.
Now to check if the remaining UVs belong to the currently selected shell you would first create an int array, then loop trough the currently selected UVs and set the corresponding indices inside the int array to 1. Then check if the ids of your remaining uv components (from your initial selection list) are set to 1 inside the array, if so they belong to the current uv shell of course.
Repeat this for all UVs of your initial selection list.

PS: for heavy UV counts you could quickly modify the int arrays indices with the corresponding UV ids trying this:
string $uvShell[] = {"[0:100000]","[300000:999999]"};
string $tmp[];
int $idxArray[];

for($comp in $uvShell){
int $numToken = `tokenize $comp "[:]" $tmp`;
for($i= int($tmp[1]);$i<= int($tmp[$numToken - 1]);$i++)
$idxArray[$i] = 1;

11 November 2012, 11:45 AM
I'm not sure I follow.
If my initial selection is of UV's belonging to two different shells, then all that polySelectBorderShell 0 will do is to select all UV's of both shells. Then it doesn't matter if I set up a double for-loop to check my two arrays (array with components from the initial selection and array with components of the "full" selection).

I've made something similiar a few days ago for counting border UVs:
// Original selection
$orgUVSel = `ls -sl`;

// Store the UVs into separate array positions
string $selArray[] = `ls -sl -fl`;
string $bufferOrg[];
tokenize $selArray[0] $bufferOrg;

// Border UV selection
$uvBorderSel = `polySelectConstraint -type 0x0010 -shell 0 -border 1 -mode 2`;

// Store the UVs into separate array positions
string $borderSelArray[] = `ls -sl -fl`;
string $bufferBorder[];
tokenize $borderSelArray[0] $bufferBorder;

int $selUVCount = `size($selArray)`;
int $borderUVCount = `size($borderSelArray)`;
int $count = 0;

// For every UV selected
for ($i = 0; $i < $selUVCount; $i++)
// Check for a match against every border UV
for ($u = 0; $u < $borderUVCount; $u++)
if ($selArray[$i] == $borderSelArray[$u]) $count++;

// Border edge count collected. Select original selection and disable constraint.
select $orgUVSel;
polySelectConstraint -disable;
...and I just don't see how something similiar can get the UV shell count.

EDIT: But maybe something like this can work:
1) The initial selection is expanded with polySelectBorderShell 0 and stored in an array called $allUVs[]. I will flatten and tokenize it the same way I did above so that each UV coord is stored in a separate array position.
2) I releoad the initial selection, and from that one I pick just ONE UV (first UV in the array for example) and then expand it to an entire shell and then I store it in an array, flatten and tokenize it just like the previous one. We call this one $oneShell[]
3) Unless all UVs in $oneShell[] - and exactly all UVs - are inside $allUVs[], we know that there are 2+ UV sets. Best way to check for a match would be to use the size-command on the arrays.

Long story short: By selecting just one UV from the initial selection and then expanding it, I get a single-shell selection. I can then compare it to another selection (expanded from the entire initial selection) in order to find out if there's only one UV shell in the initial selection.

11 November 2012, 01:51 PM


11 November 2012, 03:36 PM
Sorry i wasnt clear enough, of course i meant a comparision of the adjacent UV shell(!) of every UV component of your initial selection list against the remaining UVs of your initial selection list. I think your code will not do what you expect because first: you check the UV shell border(!) against the remaining initial selection UVs, all UVs inside the shell area remain unchecked. And besides second, although it apparently hasnt any influence in your code result, your use of tokenize also wont behave as expected. Tokenizing without a separator will cut the string at white spaces per default, but maya object paths never contain whitespaces so "tokenize $arrayA[0] $arrayB"will result into $arrayB = {$arrayA[0]}.

here is how i meant it to work:
string $uvSel[] = `ls -fl -sl`;
int $numUVs = `size $uvSel`;
int $uvIDArray[] = {}; // stores the uv shell ID for each uv compnent of the mesh object
int $associatedUVShell[] = {}; // stores the uv shell ID for each uv component of the initial uv selection list

int $shellID = 1; // 1-based shell IDs
if($associatedUVShell[$i] != 0) // if an earlier loop found the current uv associated to an uv shell we skip the remaining loop

select $uvSel[$i];
polySelectConstraint -type 0x0010 -shell 1 -border 0 -mode 2;
string $shellUVs[] = `ls -sl`; // to gain speed, do not flatten here

string $tmp[];
for($k=0;$k<`size $shellUVs`;$k++){
int $numToken = `tokenize $shellUVs[$k] "[:]" $tmp`; // cuts "[4:15]" into {"","4","15"} and returns the number of elements
for($n = int($tmp[1]); $n <= int($tmp[$numToken - 1]);$n++)
$uvIDArray[$n] = $shellID;

tokenize $uvSel[$k] "[:]" $tmp;
int $uvID = int($tmp[1]);
if($uvIDArray[$uvID] == $shellID) // the uv belongs to the currently selected uv shell, we store this info so this uv does not need
$associatedUVShell[$k] = $shellID; // to be expanded into its uv shell at a later iteration of $i

polySelectConstraint -disable;
select $uvSel;

print("uv shell[" + $i + "]: ");
if($associatedUVShell[$k] == $i)
print($uvSel[$k] + " ");

11 November 2012, 08:15 PM
This is the code I went with - and so far I haven't noticed anything wrong with it.
// Original UV selection
$orgUVSel = `ls -sl`;

// Convert the selected UVs to shells
$shellSel = `polySelectConstraint -type 0x0010 -shell 1 -mode 2`;
polySelectConstraint -disable;

// Store every UV into separate array positions
string $shellArray[] = `ls -sl -fl`;
string $bufferShell[];
tokenize $shellArray[0] $bufferShell;

// Fetch a single UV from the original selection and convert to just ONE shell
select $orgUVArray[0];
$singleShell = `polySelectConstraint -type 0x0010 -shell 1 -mode 2`;
polySelectConstraint -disable;

// Store all UVs from this single shell into separate array positions
string $singleShellArray[] = `ls -sl -fl`;
string $bufferSingleShell[];
tokenize $singleShellArray[0] $bufferSingleShell;

// Check if multiple UV shells are selected or not

int $shellUVCount = `size($singleShellArray)`;
int $allShellsUVCount = `size($shellArray)`;

if ($shellUVCount != $allShellsUVCount)
select $orgSel;
error ("Selection spans over multiple UV shells");

I also make sure that only UV's are selected before performing the above (I have a separate function for that which I make a call to prior to executing this code)

CGTalk Moderation
11 November 2012, 08:15 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.