// -- Plugin check ----------------------------------------------------------------
global proc uvCU_EnsureUnfold3D()
{
if (!`pluginInfo -q -l "Unfold3D"`) {
loadPlugin "Unfold3D";
if (!`pluginInfo -q -l "Unfold3D"`) {
error "Unfold3D plugin not available. Enable it in Plugin Manager and try again.";
}
}
}
// -- Helpers ---------------------------------------------------------------------
global proc string[] uvCU_GetExplicitUVs(string $sel[])
{
string $uvs[] = `filterExpand -sm 35 -ex 1`;
if (!size($uvs)) {
string $uvConv[] = `polyListComponentConversion -toUV $sel`;
$uvs = `filterExpand -sm 35 -ex 1 $uvConv`;
}
return $uvs;
}
// -- Camera planar (from current view) ------------------------------------------
global proc uvCU_PlanarFromCamera()
{
string $sel[] = `ls -sl`;
if (!size($sel)) error "Select mesh components or objects to project.";
string $faces[] = `filterExpand -sm 34 -ex 1`;
if (!size($faces)) {
string $toFaces[] = `polyListComponentConversion -toFace $sel`;
$faces = `filterExpand -sm 34 -ex 1 $toFaces`;
}
if (!size($faces)) error "Could not resolve faces from selection.";
select -r $faces;
polyProjection -type Planar -md p -constructionHistory 1;
print "[UV] Camera-based planar projection applied from view.\n";
}
// -- Core: Cut + Unfold ----------------------------------------------------------
// Behavior per toggle:
// - shellsOnly = 1 => strictly: polyMapCut then u3dUnfold with specific flags; TD is ignored.
// - shellsOnly = 0 => original behavior: unfold all UVs on owning meshes; TD optional.
global proc uvCU_Run(float $td, int $mapSize, int $doSetTD, int $doShellsOnly)
{
// Require seam edges
string $edges[] = `filterExpand -sm 32 -ex 1`;
if (!size($edges)) error "Select polygon edges (UV seams) first.";
// Always cut along selected edges first
select -r $edges;
polyMapCut;
if ($doShellsOnly)
{
// Edges -> UVs -> full shells (explicit UV selection)
string $edgeUVs[] = `polyListComponentConversion -fromEdge -toUV $edges`;
if (!size($edgeUVs)) error "No UVs found from selected seams.";
select -r $edgeUVs;
polySelectBorderShell 1;
string $shellUVs[] = `filterExpand -sm 35 -ex 1`;
if (!size($shellUVs)) error "Could not resolve UV shells from selected seams.";
// Always Unfold3D with requested flags; ignore TD in shells-only mode
uvCU_EnsureUnfold3D();
select -r $shellUVs;
// Flags requested: -ite 1 -p 0 -bi 1 -tf 1 -ms 1024 -rs 0
u3dUnfold -ite 1 -p 0 -bi 1 -tf 1 -ms 1024 -rs 0;
print "[UV] Cut + Unfold (Shells Only, basic flags) complete.\n";
return;
}
else
{
// Original behavior: unfold ALL UVs on the meshes owning the selected edges
string $owners[] = `ls -o $edges`;
string $xforms[];
for ($o in $owners) {
string $p[] = `listRelatives -p -pa $o`;
if (size($p)) {
int $seen = 0; for ($t in $xforms){ if ($t==$p[0]){$seen=1;break;} }
if (!$seen) $xforms[size($xforms)] = $p[0];
}
}
// Select ALL UVs on those meshes
select -cl;
for ($t in $xforms) {
string $uvs0[] = `polyListComponentConversion -toUV $t`;
select -add $uvs0;
}
string $targetUVs[] = `filterExpand -sm 35 -ex 1`;
// If still empty, seed projection and retry (rare)
if (!size($targetUVs)) {
for ($t in $xforms) {
select -r $t;
polyAutoProjection -lm 0 -pb 0 -ibd 1 -cm 0 -l 2 -sc 1 -o 1 -p 6 -ps 0.2 -ch 0;
}
select -cl;
for ($t in $xforms) { string $uvs1[] = `polyListComponentConversion -toUV $t`; select -add $uvs1; }
$targetUVs = `filterExpand -sm 35 -ex 1`;
if (!size($targetUVs)) error "Could not resolve UVs.";
}
// Unfold3D (default options), optional Texel Density
uvCU_EnsureUnfold3D();
select -r $targetUVs;
u3dUnfold;
if ($doSetTD) {
if ($td <= 0.0) error "Texel Density must be > 0.";
if ($mapSize <= 0) error "Map Size must be > 0.";
select -r $targetUVs;
texSetTexelDensity $td $mapSize;
}
print "[UV] Cut + Unfold (All UVs on mesh) complete.\n";
}
}
// -- Separate: Auto Layout Now ---------------------------------------------------
global proc uvCU_LayoutNow(float $padding)
{
string $curr[] = `ls -sl`;
if (!size($curr)) error "Select UVs or mesh components to layout.";
string $uvs[] = uvCU_GetExplicitUVs($curr);
if (!size($uvs)) error "Could not resolve UVs from selection.";
select -r $uvs;
// padding is in UV units (0..1)
polyLayoutUV -l 2 -sc 1 -fr 1 -ps $padding -ch 0;
print ("[UV] Auto Layout done (Pad: " + $padding + ").\n");
}
// -- Checkbox callback: enable/disable TD-related controls -----------------------
global proc uvCU_ToggleTD()
{
int $state = `checkBox -q -v uvCU_cbTD`;
control -e -en $state uvCU_tdFld; // enable/disable TD value
control -e -en $state uvCU_msFld; // enable/disable Map Size
control -e -en $state uvCU_padFld; // enable/disable UV Padding
control -e -en $state uvCU_layoutBtn; // enable/disable Auto Layout Now button
}
// -- Button callback to persist options & run ------------------------------------
global proc uvCU_OnRun()
{
float $td = `floatFieldGrp -q -value1 uvCU_tdFld`;
int $ms = `intFieldGrp -q -value1 uvCU_msFld`;
int $doTD = `checkBox -q -v uvCU_cbTD`;
int $shellOnly = `checkBox -q -v uvCU_cbShells`;
optionVar -fv "uvCU_texelDensity" $td;
optionVar -iv "uvCU_mapSize" $ms;
optionVar -iv "uvCU_doSetTD" $doTD;
optionVar -iv "uvCU_shellsOnly" $shellOnly;
uvCU_Run($td, $ms, $doTD, $shellOnly);
}
// -- UI --------------------------------------------------------------------------
global proc uvCU_UI()
{
string $win = "uvCutUnfoldTDWin";
if (`window -exists $win`) deleteUI -window $win;
window -title "ChatGPT X CS UV Tool" -widthHeight 540 400 $win;
columnLayout -adj true -rs 6;
// Top: toggles + main actions (both toggles default OFF)
int $defShell = 0;
int $defDoTD = 0;
checkBox -l "Only shells from selected seams" -v $defShell uvCU_cbShells;
checkBox -l "Scale to density after unfold" -v $defDoTD -cc "uvCU_ToggleTD()" uvCU_cbTD;
// Main row
rowLayout -nc 2 -cw2 180 180 -ct2 "both" "both" -co2 2 2;
button -label "CameraBased Planar" -c "uvCU_PlanarFromCamera();";
button -label "Cut + Unfold" -c "uvCU_OnRun();";
setParent ..;
separator -style "in";
// Bottom: TD/Map/Pad + Layout Now
float $defTD = (`optionVar -exists "uvCU_texelDensity"`) ? `optionVar -q "uvCU_texelDensity"` : 8.0;
int $defMap = (`optionVar -exists "uvCU_mapSize"`) ? `optionVar -q "uvCU_mapSize"` : 2048;
float $defPad = (`optionVar -exists "uvCU_padding"`) ? `optionVar -q "uvCU_padding"` : 0.005;
floatFieldGrp -label "Texel Density (px/unit)" -numberOfFields 1 -value1 $defTD uvCU_tdFld;
intFieldGrp -label "Map Size (px)" -numberOfFields 1 -value1 $defMap uvCU_msFld;
floatFieldGrp -label "UV Padding (0..1)" -numberOfFields 1 -value1 $defPad uvCU_padFld;
// Same width as the top row
rowLayout -nc 1 -cw1 364 -ct1 "both" -co1 2;
button -label "Auto Layout Now" -c "uvCU_LayoutNow(`floatFieldGrp -q -value1 uvCU_padFld`);" uvCU_layoutBtn;
setParent ..;
// Respect initial TD state (defaults OFF)
control -e -en $defDoTD uvCU_tdFld;
control -e -en $defDoTD uvCU_msFld;
control -e -en $defDoTD uvCU_padFld;
control -e -en $defDoTD uvCU_layoutBtn;
showWindow $win;
}
// Launch UI
uvCU_UI();
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter