Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Iterate through selected Materials

    General Talk
    2
    3
    691
    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.
    • M
      moko
      last edited by

      Is it possible to make an iteration through a selection of Materials.
      I'd like to rename the texture after the material. It works but only on all materials in the doc. how do i specify it on to a selection of materials?

      
      import c4d
      from c4d import gui
      from c4d import storage
      import  os
      #Welcome to the world of Python
      
      
      def changeTexture(shader):
      
      
          # shader ID
          texturePath = shader[c4d.BITMAPSHADER_FILENAME]
          # split aboslute path
          oldTexturename = os.path.split(texturePath)
          fileExtension = os.path.splitext(texturePath)
          # add prefix to
          newTexturename = matName + fileExtension[1]
          print (newTexturename)
          newTexturePath = os.path.join(oldTexturename[0], newTexturename)
          print (newTexturePath)
      
          # rename texture
          try :
              os.rename(texturePath, newTexturePath)
              print("Source path renamed to destination path successfully.")
          except OSError as error:
              print(error)
      
          # Assign the new value
          shader[c4d.BITMAPSHADER_FILENAME] = newTexturePath
          shader.Message(c4d.MSG_UPDATE)
      
      
      
      
      # Main function
      def main() :
          c4d.CallCommand(1029486) # Project Asset Inspector...
          c4d.CallCommand(1029813) # Select All
          c4d.CallCommand(1029820) # Globalize Filenames
      
          # Iterate over selected material
      
          mat = doc.GetFirstMaterial()
          while mat:
              shader = mat.GetFirstShader()
      
              global matName
              matName = mat.GetName()
              while shader:
              # Test if the current node is a bitmap shader.
                  if shader.CheckType(c4d.Xbitmap) :
                      changeTexture(shader)
                  shader (shader.GetDown())
                  shader = shader.GetNext()
              mat = mat.GetNext()
      
      
          # c4d.CallCommand(200000273) # Reload All Textures
      
      # Execute main()
      if __name__=='__main__':
          main()
      
      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @moko
        last edited by

        Hello @moko,

        thank you for reaching out to us. There are in principle two ways to do this. BaseDocument contains a handful of methods to retrieve the 'active', i.e., selected, entities of some type, e.g., objects, tags, and also materials. The method in question would be BaseDocument.GetActiveMaterials().

        There is also a more general-purpose approach via BaseList2D.GetBit() for retrieving the selection state of a node, which will also work for node types that that do not have such special purpose methods. For details, please see the example at the end of this posting.

        Cheers,
        Ferdinand

        """Example for determining the selection state of BaseList2D nodes via GetBit().
        
        To be run as a Script Manger script. Will print out the names of the selected
        materials.
        
        As discussed in:
            https://developers.maxon.net/forum/topic/13446/
        """
        
        import c4d
        
        def main():
            """
            """
            # We can get the active Materials with BaseDocument.GetActiveMaterials()
            for activeMaterial in doc.GetActiveMaterials():
                print (f"{activeMaterial.GetName()} is a selected Material.")
        
            print ("\n", "-" * 100, "\n")
        
            # Or we can iterate over the materials and use the bit flags of the nodes
            # to determine their selection state. The advantage here is that this will
            # work for any BaseList2D and not only the ones (objects, tags, materials,
            # etc.) where specific methods exist to retrieve the selected/active ones.
            # The relevant method is BaseList2D.GetBit() and the relevant bit mask is
            # BIT_ACTIVE - which indicates the selection state of the BaseList2D.
        
            # Get the first material like you did.
            material = doc.GetFirstMaterial()
            if not material:
                return
        
            while material:
                # Print out only materials that are selected.
                if material.GetBit(c4d.BIT_ACTIVE):
                    print (f"{material.GetName()} is a selected Material.")
                material = material.GetNext()
        
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        M 1 Reply Last reply Reply Quote 0
        • M
          moko @ferdinand
          last edited by

          @ferdinand

          Thank you very much! The second way works great. I didnt get the first approach to work, but the second does well 🙂

          Here is the script if someone needs it. It is probably messy I am not a programmer, but it does write the names of the selected materials into the texturname

          
          import c4d
          from c4d import gui
          from c4d import storage
          import  os
          #Welcome to the world of Python
          
          
          def changeTexture(shader):
          
          
              # shader ID
              texturePath = shader[c4d.BITMAPSHADER_FILENAME]
              # split aboslute path
              oldTexturename = os.path.split(texturePath)
              fileExtension = os.path.splitext(texturePath)
              # add prefix to
              newTexturename = matName + fileExtension[1]
              print (newTexturename)
              newTexturePath = os.path.join(oldTexturename[0], newTexturename)
              print (newTexturePath)
          
              # rename texture
              try :
                  os.rename(texturePath, newTexturePath)
                  print("Source path renamed to destination path successfully.")
              except OSError as error:
                  print(error)
          
              # Assign the new value
              shader[c4d.BITMAPSHADER_FILENAME] = newTexturePath
              shader.Message(c4d.MSG_UPDATE)
          
          
          # Main function
          def main() :
              c4d.CallCommand(1029486) # Project Asset Inspector...
              c4d.CallCommand(1029816) # Select Assets of Active Elements
              c4d.CallCommand(1029820) # Globalize Filenames
          
              # Iterate over selected material
              material = doc.GetFirstMaterial()
              if not material:
                  return
          
              while material:
                  if material.GetBit(c4d.BIT_ACTIVE):
                      shader = material.GetFirstShader()
          
                      global matName
                      matName = material.GetName()
                      while shader:
                      # Test if the current node is a bitmap shader.
                          if shader.CheckType(c4d.Xbitmap) :
                              changeTexture(shader)
                          shader (shader.GetDown())
                          shader = shader.GetNext()
          
                  material = material.GetNext()
          
              c4d.CallCommand(200000273) # Reload All Textures
          
          # Execute main()
          if __name__=='__main__':
              main()
          
          1 Reply Last reply Reply Quote 0
          • First post
            Last post