PSD Layersets



  • 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/Cinema4DPythonSDK/html/modules/c4d/CustomDataType/LayerSet/index.html



  • 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



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

    Thanks works like a charm!



  • 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()
    


  • 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()
    


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

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


Log in to reply