ZBrushCentral

Copying and pasting UVs through ZScript

Hi,

I’d like to know if anyone has any clues as to how to copy and paste UV tiles through ZScript, just like UV Master allows you to do. I have read through all of the command reference for ZScript, but aside from Mesh3DGet, no other command seems to reference UVs at all.

Many thanks

nope sorry its not possible to cycle from your script to uvmaster and get back to your script process. because your script is no longer reachable so the process just stop and there is no workaround for that.
But
you can create a plugin with a dll to directly read the uv data from the object01.obj and copyand write the
data to the object02.obj file and reload it in zbrush. That’s the only way out.

you can create a plugin with a dll to directly read the uv data from the object01.obj and copyand write the
data to the object02.obj file and reload it in zbrush. That’s the only way out.

I see, so it is possible to create an OBJ that is only made of UV data. This is for a highly specific situation where the polygroups of one mesh will not be identical to the other’s, so I really only want to carry the UVs over, just like UV Master does, in order to conserve polygroups. I will read up on OBJ and then get to work.

Thanks man!

Hi! I hope this helps you man. The codes for copying and pasting uvs are super simple.

[IButton, CopyUVS, “”,
[IFreeze,

[IPress, Tool:Visibility:ShowPt] // Make sure to show all polygons before copying in the memory [IPress, Tool:Geometry:Copy] ]

]

[IButton, PasteUVS, “”,
[IFreeze,
[IPress, Tool:Visibility:ShowPt]
[IPress, “Tool:Geometry:Paste Replace”]

]

]

You could confirm if the uvs are transferred succesfully by pressing this button , Tool:Uv Map:Morph UV

Hi! I hope this helps you man. The codes for copying and pasting uvs are super simple.

[IButton, CopyUVS, “”,
[IFreeze,

[IPress, Tool:Visibility:ShowPt] // Make sure to show all polygons before copying in the memory [IPress, Tool:Geometry:Copy] ]

]

[IButton, PasteUVS, “”,
[IFreeze,
[IPress, Tool:Visibility:ShowPt]
[IPress, “Tool:Geometry:Paste Replace”]

]

]

You could confirm if the uvs are transferred succesfully by pressing this button , Tool:Uv Map:Morph UV

the big issue here is that you replaces the geometry too.
the only way to copyuvs from a mesh to another, is to use uvmaster copyuvs /pasteuvs
and like i say in my previous message, it can’t to work with a custom zscript because it end your script at the moment you press a button item in uvmaster plugin.
you can only do it manually.

I wrote a sample script that copies and pastes uv maps between 2 geometries that have the same geometry data. This is a workaround that works because you cannot literally copy and paste uvs. This preserves polygroups,material. polypaints, layers, morph target, etc. In short it only tranfers uv maps. You could try it. modify, include in your scripts. You could call the routine in your scripts if you want to use it but make sure to edit the NOte messages to your likings. I might post a short clip demonstrating this one.

This is the ZScript Text File
CopyPasteUV.txt (5.16 KB)

[RoutineDef, CopyUV, // ROUTINE FOR COPYING UVS[IFreeze,
[Note, “Copying UVs. Please wait…”]

[VarSet, isSuccessful, 0]

[VarSet, hasUV, 0]

[VarSet, morphUVStat, [IGetStatus, “Tool:UV Map:Morph UV”]]

[If, #morphUVStat ,

[VarSet, hasUV, 1]

,]

[If, #hasUV, // has UV

[IPress, Tool:Visibility:ShowPt] // Make sure to show all polygons before copying in the memory

[VarSet,sdivCurrent, [IGet,“Tool:Geometry:SDiv”]]

[ISet, “Tool:Geometry:SDiv”, 1] // Copy from the lowest level

[IPress, Tool:Geometry:Copy]

[ISet, “Tool:Geometry:SDiv”, #sdivCurrent]

[VarSet, isSuccessful, 1]

, // has no UV

[VarSet, isSuccessful, 0]

]

[VarSet, [Var,successOuput], #isSuccessful] // Return value

]
, successOuput]

[RoutineDef, PasteUV, // ROUTINE FOR PASTING UVS[IFreeze,
[Note, “Pasting UVs. Please wait…”]

[VarSet, currSubTool,[SubToolGetActiveIndex]]

[IPress, Tool:Visibility:ShowPt] // Shows any polygons first to make it properly work.

[VarSet, currSubD,[IGet, Tool:Geometry:SDiv]] // Store this so you can restore the current subdivision level later.

[ISet, Tool:Geometry:SDiv, 1]// Set the subdiv to the lowest level

[VarSet, polyCount1, 0]

[Mesh3DGet,0,polyCount1]//Get the polygon count of level 1

[IPress, Tool:SubTool: Duplicate]

[IPress, “Tool:Geometry:Paste Replace”]

[VarSet, UVMorphStat, [IGetStatus, “Tool:UV Map:Morph UV”]]

[VarSet , hasUV,#UVMorphStat]// Double checks if the source mesh has uv map

[If, #hasUV,// SOURCE MESH HAS UV MAP

//Validates if the source mesh and the target mesh has the same level 1 polygon data

[ISet, Tool:Geometry:SDiv, 1]// Set the subdiv to the lowest level

[VarSet, polyCount2, 0]

[Mesh3DGet,0,polyCount2]//Get the polygon count of level 1

[VarSet, isLevel1TheSame, 0]

[If, #polyCount1 == #polyCount2,

[VarSet, isLevel1TheSame, 1] // It means it is valid and will proceed in transferring uvs.

,

[VarSet, isLevel1TheSame, 0] // It means it is invalid and will not transfer any uv data.

]

[If, #isLevel1TheSame,//VALID

[VarSet, morphTimer,[IGet, “Preferences:Interface:Morph UV Timer”]]//Save this settings so it can be restore later

[ISet, “Preferences:Interface:Morph UV Timer”, 0] // Set this to 0 so uv morphing is not animating.

[IPress, “Tool:UV Map:Morph UV”]

// These make sure that these settings are always in their default values to make it work properly.

[IPress, Tool:Export:Txr]

[IUnPress, Tool:Export:Flp]

[IPress, Tool:Export:Mrg]

[IPress, Tool:Export:Grp]

[IPress, Tool:Export:Qud]

[ISet, Tool:Export:Scale, 1]

[ISet, “Tool:Export:X Offset”, 0]

[ISet, “Tool:Export:Y Offset”, 0]

[ISet, “Tool:Export:Z Offset”, 0]

[VarSet, filePath,[FileNameResolvePath, “UVMesh.obj”]]

[FileNameSetNext, #filePath]

[IPress, Tool:Export]

[ISet, Edit:Tool:UndoCounter, 1]

[IPress, Edit:ToolDelUH]

[SubToolSelect, ([SubToolGetActiveIndex]-1)]

[ISet, Tool:Polygroups:PTolerance, .1]

[IPress, “Tool:Polygroups:From Polypaint”]

[IPress, Tool:UV Map:Uvp]

[IPress, “Tool:UV Map:Morph UV”]

// These make sure that these settings are always in their default values to make it work properly.

[IUnPress, Tool:Import:Mrg]

[IUnPress, Tool:Import:Add]

[ISet, Tool:Import:Tri2Quad, 0]

[ISet, Tool:Import:Weld, 0]

[FileNameSetNext, #filePath]

[IPress, “Tool:Import: Import”]

// These make sure that these settings are always in their default values to make it work properly.

[IPress, Tool:Export:Txr]

[IUnPress, Tool:Export:Flp]

[IPress, Tool:Export:Mrg]

[IPress, Tool:Export:Grp]

[IPress, Tool:Export:Qud]

[ISet, Tool:Export:Scale, 1]

[ISet, “Tool:Export:X Offset”, 0]

[ISet, “Tool:Export:Y Offset”, 0]

[ISet, “Tool:Export:Z Offset”, 0]

[FileNameSetNext, #filePath]

[IPress, Tool:Export]

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[IPress, Tool:UV Map:Uvp]

[IPress, “Tool:UV Map:Morph UV”]

[FileNameSetNext, #filePath]

[IPress, “Tool:Import: Import”]

[IPress, “Tool:UV Map:Morph UV”]

[ISet, Tool:Geometry:SDiv, #currSubD]

[ISet, “Preferences:Interface:Morph UV Timer”, #morphTimer] //Restore this setting.

[VarSet, [Var, successOuput],1 ] // Return value

,//INVALID

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[SubToolSelect, #currSubTool]

[VarSet, [Var, successOuput],0 ]// Return value

]

, // SOURCE MESH HAS NO UV MAP

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[SubToolSelect, #currSubTool]

[VarSet, [Var, successOuput],0 ]// Return value

]

]
, successOuput]

[IButton, CopyUVS, “”,[VarSet, success, 0]
[IKeyPress, ‘1’,
[RoutineCall, CopyUV, success]

]
[If, #success == 0 ,
[Note, “Mesh has no UV Map. Copy failed.”]

,]
]

[IButton, PasteUVS, “”,[VarSet, success, 0]
[IKeyPress, ‘1’,
[RoutineCall, PasteUV, success]

]
[If, #success,
[Note

, “UV pasting successful.”]

,]
]

CopyPasteUV.txt (5.16 KB)

I apologize because the previous code has issues with polygroups and masking. I fixed it and this is now the updated one,
CopyPasteUVNew.txt (5.39 KB)
CopyPasteUVNew.txt (5.39 KB)
. I modified it and removed some lines. It is now a little bit faster and optimized. Handling polygroups and masking are now working well. Below is a short demo.

[RoutineDef, CopyUV, // ROUTINE FOR COPYING UVS[IFreeze,
[Note, “Copying UVs. Please wait…”]

[VarSet, isSuccessful, 0]

[VarSet, hasUV, 0]

[VarSet, morphUVStat, [IGetStatus, “Tool:UV Map:Morph UV”]]

[If, #morphUVStat ,

[VarSet, hasUV, 1]

,]

[If, #hasUV, // has UV

[IPress, Tool:Visibility:ShowPt] // Make sure to show all polygons before copying in the memory

[VarSet,sdivCurrent, [IGet,“Tool:Geometry:SDiv”]]

[ISet, “Tool:Geometry:SDiv”, 1] // Copy from the lowest level

[IPress, Tool:Geometry:Copy]

[ISet, “Tool:Geometry:SDiv”, #sdivCurrent]

[VarSet, isSuccessful, 1]

, // has no UV

[VarSet, isSuccessful, 0]

]

[VarSet, [Var,successOuput], #isSuccessful] // Return value

]
, successOuput]

[RoutineDef, PasteUV, // ROUTINE FOR PASTING UVS[IFreeze,
[Note, “Pasting UVs. Please wait…”]

[VarSet, currSubTool,[SubToolGetActiveIndex]]

[IPress, Tool:Visibility:ShowPt] // Shows any polygons first to make it properly work.

[VarSet, currSubD,[IGet, Tool:Geometry:SDiv]] // Store this so you can restore the current subdivision level later.

[VarSet, undo1, [IGet, Edit:Tool:UndoCounter]]

[ISet, Tool:Geometry:SDiv, 1]// Set the subdiv to the lowest level

[VarSet, polyCount1, 0]

[Mesh3DGet,0,polyCount1]//Get the polygon count of level 1

[IPress, Tool:SubTool: Duplicate]

[IPress, “Tool:Geometry:Paste Replace”]

[VarSet, UVMorphStat, [IGetStatus, “Tool:UV Map:Morph UV”]]

[VarSet , hasUV,#UVMorphStat]// Double checks if the source mesh has uv map

[If, #hasUV,// SOURCE MESH HAS UV MAP

//Validates if the source mesh and the target mesh has the same level 1 polygon data

[ISet, Tool:Geometry:SDiv, 1]// Set the subdiv to the lowest level

[VarSet, polyCount2, 0]

[Mesh3DGet,0,polyCount2]//Get the polygon count of level 1

[VarSet, isLevel1TheSame, 0]

[If, #polyCount1 == #polyCount2,

[VarSet, isLevel1TheSame, 1] // It means it is valid and will proceed in transferring uvs.

,

[VarSet, isLevel1TheSame, 0] // It means it is invalid and will not transfer any uv data.

]

[If, #isLevel1TheSame,//VALID

[VarSet, soloFl, [IGetFlags, Transform:Solo]]

[IPress, Transform:Solo]

[VarSet, morphTimer,[IGet, “Preferences:Interface:Morph UV Timer”]]//Save this settings so it can be restore later

[ISet, “Preferences:Interface:Morph UV Timer”, 0] // Set this to 0 so uv morphing is not animating.

[IUnPress, “Tool:UV Map:Morph UV”]

[IPress, “Tool:UV Map:Morph UV”]

// These make sure that these settings are always in their default values to make it work properly.

[IPress, Tool:Export:Txr]

[IUnPress, Tool:Export:Flp]

[IPress, Tool:Export:Mrg]

[IPress, Tool:Export:Grp]

[IPress, Tool:Export:Qud]

[ISet, Tool:Export:Scale, 1]

[ISet, “Tool:Export:X Offset”, 0]

[ISet, “Tool:Export:Y Offset”, 0]

[ISet, “Tool:Export:Z Offset”, 0]

[VarSet, filePath,[FileNameResolvePath, “UVMesh.obj”]]

[FileNameSetNext, #filePath]

[IPress, Tool:Export]

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[SubToolSelect, #currSubTool]

[VarSet, undo2, [IGet, Edit:Tool:UndoCounter]]

[If, #undo2 > #undo1,

[mergeundo]

,]

[IUnPress, “Tool:UV Map:Morph UV”]// This unpressing makes it sure that it is off before the uv mapping

[mergeundo]

[IPress, Tool:UV Map:GUVTiles]// Creates a map using GUVTiling

[mergeundo]

[IPress, “Tool:UV Map:Morph UV”]

[mergeundo]

[IPress, “Tool:Polypaint:Polypaint From Polygroups”]

[mergeundo]

[IPress, Tool:Masking:Inverse]

[mergeundo]

[IPress, “Tool:Polypaint:Polypaint From Polygroups”]

[mergeundo]

[IPress, Tool:Masking:Inverse]

// These make sure that these settings are always in their default values to make it work properly.

[IUnPress, Tool:Import:Mrg]

[IUnPress, Tool:Import:Add]

[ISet, Tool:Import:Tri2Quad, 0]

[ISet, Tool:Import:Weld, 0]

[FileNameSetNext, #filePath]

[mergeundo]

[IPress, “Tool:Import: Import”]

[ISet, “Tool:Polygroups:PTolerance”, .5]

[mergeundo]

[IPress, “Tool:Polygroups:From Polypaint”]

[mergeundo]

[IUnPress, “Tool:UV Map:Morph UV”]

[VarSet, subDivLvl, [IGet, Tool:Geometry:SDiv]]

[If, #subDivLvl == #currSubD ,

,

[mergeundo]

]

[ISet, Tool:Geometry:SDiv, #currSubD]

[ISet, “Preferences:Interface:Morph UV Timer”, #morphTimer] //Restore this setting.

[If, (#soloFl == 8) || (#soloFl == 10) ,

[IUnPress, Transform:Solo]

,]

[VarSet, [Var, successOuput],1 ] // Return value

,//INVALID

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[SubToolSelect, #currSubTool]

[VarSet, [Var, successOuput],0 ]// Return value

]

, // SOURCE MESH HAS NO UV MAP

[IKeyPress, ‘2’,

[IPress, Tool:SubToolDelete]

]

[SubToolSelect, #currSubTool]

[VarSet, [Var, successOuput],0 ]// Return value

]

]
, successOuput]

[IButton, CopyUVS, “”,[VarSet, success, 0]
[IKeyPress, ‘1’,
[RoutineCall, CopyUV, success]

]
[If, #success == 0 ,
[Note, “Mesh has no UV Map. Copy failed.”]

,]
]

[IButton, PasteUVS, “”,[VarSet, success, 0]
[IKeyPress, ‘1’,
[RoutineCall, PasteUV, success]

]
[If, #success,
[Note, “UV pasting successful.”]

,]
]

GG JRoC

I wrote a sample script that copies and pastes uv maps between 2 geometries that have the same geometry data.

First of all, spectacular work, I haven’t checked the forum in a while and already figured it out how to do it through a DLL, but yours is superb!

Second, what in the world? The Morph UV actually has a physical effect on the mesh? I’ve been using it for the longest time and never noticed that, I thought it was only for preview purposes.

I will be using mine and can post it here when I get around to doing it, if anyone is interested, but praise be to you for conjuring up that awesome in-house solution of yours. Next time I come across an apparent impossibility in ZScript, I will remember you :+1: