Realign uv mapping from script
-
On 09/02/2017 at 01:19, xxxxxxxx wrote:
Hi,
I am trying to realign UV mapping of an object from script. I want the same result from script that I get when I press the apply button in the UV optimal mapping tool.
Here is the settings and the result when i press the apply button:
https://postimg.org/image/oh298vdzr/
Here is the code that I expect to do the same thing (I have used the code from Andreas in this post: https://developers.maxon.net/forum/topic/9738/13094_new-calluvcommand and changed the settings) :
import c4d
from c4d import utils
from c4d import gui
from c4d.modules import bodypaintdef applyRealign(doc,obj) :
for tag in obj.GetTags() :
if type(tag) == c4d.UVWTag:
uvwTag = tag
doc.SetActiveObject(obj)
doc.SetActiveTag(uvwTag)# Retrieves active UVSet
handle = bodypaint.GetActiveUVSet(doc, c4d.GETACTIVEUVSET_ALL)
if not handle:
print "No active UVSet!"
returnsettings = c4d.BaseContainer()
settings[c4d.OPTIMALMAPPING_PRESERVEORIENTATION] = 0
settings[c4d.OPTIMALMAPPING_STRETCHTOFIT] = 0
settings[c4d.OPTIMALMAPPING_EQUALIZEAREA] = 1
settings[c4d.OPTIMALMAPPING_SPACING] = 0.02# Retrieves UVW list
uvw = handle.GetUVW()
if uvw is None:
return# Calls UVCOMMAND_TRANSFORM to change UVW list
ret = bodypaint.CallUVCommand(handle.GetPoints(), handle.GetPointCount(), handle.GetPolys(), handle.GetPolyCount(), uvw,
handle.GetPolySel(), handle.GetUVPointSel(), obj, handle.GetMode(), c4d.UVCOMMAND_REALIGN, settings)
if not ret:
print "CallUVCommand() failed!"
returnprint "CallUVCommand() successfully called"
# Sets the transformedUVW from Texture View
if handle.SetUVWFromTextureView(uvw, True, True, True) :
print "UVW from Texture View successfully set"
else:
print "UVW from Texture View failed to be set!"# Releases active UVSet
bodypaint.FreeActiveUVSet(handle)def main() :
# Get the selected objects, including children.
selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
if len(selection) <= 0:
gui.MessageDialog('Must select objects!')
return# doc.StartUndo() # Start undo block.
for i in range(0,len(selection)) :
sel = selection applyRealign(doc,sel)if __name__=='__main__':
main()And this is the resulting uv mapping after running the script:
https://postimg.org/image/sc11xp7rr/
It seems that OPTIMALMAPPING_SPACING is not set to the specified value. It seems that the resulting spacing is around 50%. I have tried different values for OPTIMALMAPPING_SPACING but the resulting mapping always seem to use a bigger spacing than requested.
I am missing something or is this a bug?
Cheers,
Per
-
On 10/02/2017 at 02:13, xxxxxxxx wrote:
Hi,
The value 0.02 for OPTIMALMAPPING_SPACING is valid. The issue isn't there but in other parts of your script (please use
tags for better formatting of code snippets).
With the following loop the script doesn't run fine:
for i in range(0,len(selection)) : sel = selection
In fact the previous lopp isn't needed. You can call applyRealign(doc) once with just the active document.
Also don't change the active object and tag from the script. TempUVHandle.GetBaseObject() gives the object for the current UV context.So the fixed script that gives the same result as the UI is:
import c4d from c4d import gui from c4d.modules import bodypaint def **applyRealign(doc)** : # Retrieves active UVSet handle = bodypaint.GetActiveUVSet(doc, c4d.GETACTIVEUVSET_ALL) if not handle: print "No active UVSet!" return settings = c4d.BaseContainer() settings[c4d.OPTIMALMAPPING_PRESERVEORIENTATION] = **False** settings[c4d.OPTIMALMAPPING_STRETCHTOFIT] = **False** settings[c4d.OPTIMALMAPPING_EQUALIZEAREA] = **True** settings[c4d.OPTIMALMAPPING_SPACING] = 0.02 # Retrieves UVW list uvw = handle.GetUVW() if uvw is None: return # Calls UVCOMMAND_TRANSFORM to change UVW list ret = bodypaint.CallUVCommand(handle.GetPoints(), handle.GetPointCount(), handle.GetPolys(), handle.GetPolyCount(), uvw, handle.GetPolySel(), handle.GetUVPointSel(), **handle.GetBaseObject()** , handle.GetMode(), c4d.UVCOMMAND_REALIGN, settings) if not ret: print "CallUVCommand() failed!" return print "CallUVCommand() successfully called" # Sets the transformedUVW from Texture View if handle.SetUVWFromTextureView(uvw, True, True, True) : print "UVW from Texture View successfully set" else: print "UVW from Texture View failed to be set!" # Releases active UVSet bodypaint.FreeActiveUVSet(handle) def main() : # Get the selected objects, including children. selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN) if len(selection) <= 0: gui.MessageDialog('Must select objects!') return **applyRealign(doc)** if __name__=='__main__': main()
-
On 13/02/2017 at 02:01, xxxxxxxx wrote:
Hi and thanks for your reply
I should have described better what I want the script to do. I want the script to iterate all selected objects and automatically remap the UVs without having to manually make one active.
With your changes only one object seems to be remapped and only the active UV.
Cheers,
Per
-
On 13/02/2017 at 02:25, xxxxxxxx wrote:
Hi Per,
Thanks for the clarification.
I think you're just missing a call to c4d.EventAdd() after setting the active object and tag (only call SetActiveObject() once for an object in applyRealign()) so that Cinema updates all its data for the document.
Also the loop in main() should be changed to (if not done yet) :
for obj in selection: applyRealign(doc, obj)