Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Realign uv mapping from script

    Scheduled Pinned Locked Moved PYTHON Development
    4 Posts 0 Posters 496 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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 bodypaint

      def 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!"
                    return

      settings = 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!"
                    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

      #  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

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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()
        
        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          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

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            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)
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post