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

    PSD Layersets

    Scheduled Pinned Locked Moved PYTHON Development
    6 Posts 0 Posters 864 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 24/07/2017 at 01:30, xxxxxxxx wrote:

      Hello,

      Is it possible to set layers from .psd files? 
      I did find layersets in the SDK, but i cant find a way to set them.

      https://developers.maxon.net/docs/py/2023_2/modules/c4d/CustomDataType/LayerSet/index.html

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

        On 24/07/2017 at 08:13, xxxxxxxx wrote:

        Here a code I did 6 months ago. So it's not the cleanest but it's working and since this subject is not very well documented I guess It gonna help you 😉

            def setAlpha(self,path,shader) :
                if path.endswith( ('.psd' , '.PSD') ) : #PSD
                    bc = c4d.BaseContainer()
                    bc.SetFilename(c4d.LOADTEXTURE_FILENAME, path.encode('utf-8'))
                    tex = c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=self.doc, tex=None, bc=bc)
                    
                    if tex is False:
                        print path
                        return
                    layer = tex.GetFirstLayer()
                    layerName = layer.GetName()
                    layermode = c4d.LAYERSETMODE_LAYERALPHA
                    
                    c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_FORCECLOSETEXTURE, doc=self.doc, tex=tex, bc=c4d.BaseContainer())
                    
                else:#tiff, But if you already know the name simply use this
                    layerName = 'Alpha'
                    layermode = c4d.LAYERSETMODE_ALPHAS
                    
                
                layerSet = c4d.LayerSet()
                layerSet.SetMode(layermode)
                layerSet.AddLayer(layerName)
                shader[c4d.BITMAPSHADER_LAYERSET] = layerSet
        

        If it's an psd it load it and have a c4d.modules.bodypaint.PaintTexture object.
        Then now you are able to list all the layer. I my case I always used the first layer, but you can loop using GetNext/GetDown, in other way if you already know the name of the layer simply use the exemple for the tiff 😉

        Then after you just have to create a LayerSet and set thoses data.
        Hope it's helped

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

          On 26/07/2017 at 08:25, xxxxxxxx wrote:

          Thanks works like a charm!

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

            On 27/07/2017 at 03:12, xxxxxxxx wrote:

            Little extra question:

            I have a test code that can find a psd layer by name and then sets it. but it returns only the name. I need it to return the path in the psd. like somefolder/somefolder/lmb_tp

            right now it only returns the name of layer that i'm seeking.

            import c4d
            from c4d import gui
            #Welcome to the world of Python
              
            path = 'C:/Program Files/MAXON/CINEMA 4D R18/library/scripts/rig_menu/test.psd'
              
            def main() :
                bc = c4d.BaseContainer()
                bc.SetFilename(c4d.LOADTEXTURE_FILENAME, path.encode('utf-8'))
                tex = c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=doc, tex=None, bc=bc)
              
                mat = doc.SearchMaterial("Mat.1")
                layerName = '' 
                layers = tex.GetFirstLayer()
                #search for name and store in layername
                layerName = FindLayerPSD(layers, 'lmb_tp')
                    
                c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_FORCECLOSETEXTURE, doc=doc, tex=tex, bc=c4d.BaseContainer())   
                
                layerSet = c4d.LayerSet()
                #set color
                layermode = c4d.LAYERSETMODE_LAYERS
                layerSet.AddLayer(layerName)
                layerSet.SetMode(layermode)       
                sha = mat[c4d.MATERIAL_COLOR_SHADER]
                sha[c4d.BITMAPSHADER_LAYERSET] = layerSet
                mat[c4d.MATERIAL_COLOR_SHADER] = sha
                #set alpha
                layermode = c4d.LAYERSETMODE_LAYERALPHA
                layerSet.AddLayer(layerName)
                layerSet.SetMode(layermode)       
                sha = mat[c4d.MATERIAL_ALPHA_SHADER]
                sha[c4d.BITMAPSHADER_LAYERSET] = layerSet
                mat[c4d.MATERIAL_ALPHA_SHADER] = sha
                #force redraw    
                c4d.CallCommand(12147)
                c4d.EventAdd()
              
              
            def GetNextObject(op) :
                if op==None:
                    return None  
                if op.GetDown() :
                    return op.GetDown()  
                while not op.GetNext() and op.GetUp() :
                    op = op.GetUp()  
                return op.GetNext()
             
            def FindLayerPSD(op, gname) : 
                if op is None:
                    return
                count = 0  
                while op:
                    count += 1
                    if gname in op.GetName() :  
                        layername = op.GetName()       
                    op = GetNextObject(op)
                return layername
               
            if __name__=='__main__':
                main()
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 27/07/2017 at 03:42, xxxxxxxx wrote:

              I did it for object but since BaseObject and c4d.modules.bodypaint.PaintTexture are both BaseList2D that change nothing.

              I comment it(maybe too much? :p) but if you still don't understand a part feel free to ask 😉

              import c4d
                
              def get_full_path(op) :
                  full_path = list()
                  while op:
                      full_path.append(op.GetName())
                      op = op.GetUp()
                      
                  #Since we build from bottom to parent we need to reverse the list to keep it consistent
                  full_path.reverse()
                
                  #Then we join for build our string line
                  str_full_path = "/".join(full_path)
                  return str_full_path
                
              def find_by_name(op, name_to_find) :
                  #We loop throught all op
                  while op:        
                      #If the name is the same then our name to find we lunch our function to get the full path then we return
                      if op.GetName() == name_to_find:
                          return get_full_path(op)
                      
                      #We lunch recusrive search like that we get also child object
                      #Since it's recursive function that mean a child function can have fund the object
                      #Then if a child function make a return we also need to return in the parent function
                      return_value = find_by_name(op.GetDown(), name_to_find)
                      if return_value is not None:
                          return return_value
                      
                      #then finally we go the next object
                      op = op.GetNext()
                      
                  #If we return here that mean we never get op.GetName == name_to_find so we return None
                  return None
                
              def main() :
                  print find_by_name(doc.GetFirstObject(), "aa")
                
              if __name__=='__main__':
                  main()
              
              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 27/07/2017 at 04:27, xxxxxxxx wrote:

                Thanks for the fast reply, exactly what i was looking for 😄

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post