Cinema Gradient, weird behaviour



  • Hi all,

    I encountered a very weird behaviour. I tried to write a script in python which reads all the knot-values of one gradient and set those value to another gradient.
    I can read the knots by calling GetKnot().
    BUT when I try to extract a certain info from a Knot (for example the position) I get wrong results. So when transfering these infos to another gradient, the gradient is shown wrong.

    Thats the Code:

    import c4d
    from c4d import gui
    
    
    def main():
        mat = doc.GetFirstMaterial()           #Gets the first material in the materials manager
        shdr1 = mat[c4d.MATERIAL_COLOR_SHADER]
    
        shd = c4d.BaseList2D(1011100) # Gradient
        mat[c4d.MATERIAL_DIFFUSION_SHADER] = shd
        mat.InsertShader(shd)
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
    
        shdr2 = mat[c4d.MATERIAL_DIFFUSION_SHADER]
    
    
        grad1 = shdr1[c4d.SLA_GRADIENT_GRADIENT]
        grad2 = shdr2[c4d.SLA_GRADIENT_GRADIENT]
    
    
        grad1_knot1 = grad1.GetKnot(0)
        print("Knot1 = " + str(grad1_knot1))
        grad1_knot2 = grad1.GetKnot(1)
        print("Knot2 = " + str(grad1_knot2))
        grad1_knot3 = grad1.GetKnot(2)
        print("Knot3 = " + str(grad1_knot3))
    
        index1 = grad1_knot1['index']
        print("Index" + " " + str(index1))
        index2 = grad1_knot2['index']
        print("Index" + " " + str(index2))
        index3 = grad1_knot3['index']
        print("Index" + " " + str(index3))
        pos1 = grad1_knot1['pos']
        print("Position" + " " + str(pos1))
        pos2 = grad1_knot2['pos']
        print("Position" + " " + str(pos2))
        pos3 = grad1_knot2['pos']
        print("Position" + " " + str(pos3))
        col1 = grad1_knot1['col']
        print("Color" + " " + str(col1))
        col2 = grad1_knot2['col']
        print("Color" + " " + str(col2))
        col3 = grad1_knot2['col']
        print("Color" + " " + str(col3))
        bri1 = grad1_knot1['brightness']
        print("Brightness" + " " + str(bri1))
        bri2 = grad1_knot2['brightness']
        print("Brightness" + " " + str(bri2))
        bri3 = grad1_knot2['brightness']
        print("Brightness" + " " + str(bri3))
        grad2.FlushKnots()
    
        grad2.InsertKnot(col=col1, pos=pos1,index=index1)
        grad2.InsertKnot(col=col2, pos=pos2,index=index2)
        grad2.InsertKnot(col=col3, pos=pos3,index=index3)
        shdr2[c4d.SLA_GRADIENT_GRADIENT] =  grad2
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
        c4d.EventAdd()
        
    # Execute main()
    if __name__=='__main__':
        main()
    

    And thats the result I get from the console and obviously the second gradient looks like that (wrong), too.

    "Knot1 = {'index': 1, 'bias': 0.5, 'pos': 0.3, 'col': Vector(1, 1, 1), 'brightness': 1.0}
    Knot2 = {'index': 2, 'bias': 0.5, 'pos': 1.0, 'col': Vector(1, 1, 1), 'brightness': 1.0}
    Knot3 = {'index': 3, 'bias': 0.5, 'pos': 0.5, 'col': Vector(1, 0.6, 0.5), 'brightness': 1.0}
    Index 1
    Index 2
    Index 3
    Position 0.3
    Position 1.0
    Position 1.0
    Color Vector(1, 1, 1)
    Color Vector(1, 1, 1)
    Color Vector(1, 1, 1)
    Brightness 1.0
    Brightness 1.0
    Brightness 1.0
    "

    As you can see: When calling GetKnot() the infos of the Knots are right. But when extracting for example col of those Knots, The results are wrong. They all show Vector(1, 1, 1).

    What is happening here?

    Cheers,
    PdZ



  • I coded a solution. But this was so much work and effort to get it work.
    Its not very sexy though. BUT it works.

    import c4d
    from c4d import gui
    
    
    def main():
        mat = doc.GetFirstMaterial()           #Gets the first material in the materials manager
        shdr1 = mat[c4d.MATERIAL_COLOR_SHADER]
    
        shd = c4d.BaseList2D(1011100) # Gradient
        mat[c4d.MATERIAL_DIFFUSION_SHADER] = shd
        mat.InsertShader(shd)
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
    
        shdr2 = mat[c4d.MATERIAL_DIFFUSION_SHADER]
    
    
        grad1 = shdr1[c4d.SLA_GRADIENT_GRADIENT]
        grad2 = shdr2[c4d.SLA_GRADIENT_GRADIENT]
    
    
        grad1_knot1 = str(grad1.GetKnot(0)).replace("'", "").replace(":", " =").replace("Vector", "c4d.Vector").replace("{", "").replace("}", "")
        grad1_knot2 = str(grad1.GetKnot(1)).replace("'", "").replace(":", " =").replace("Vector", "c4d.Vector").replace("{", "").replace("}", "")
        grad1_knot3 = str(grad1.GetKnot(2)).replace("'", "").replace(":", " =").replace("Vector", "c4d.Vector").replace("{", "").replace("}", "")
        print(grad1_knot1)
        
        # index
        newgrad1_knot1_index_nr = grad1_knot1.find(",")
        newgrad1_knot1_index = int(grad1_knot1[newgrad1_knot1_index_nr-1:newgrad1_knot1_index_nr])
        
        # bias
        newgrad1_knot1_bias_nr = grad1_knot1.find(",", newgrad1_knot1_index_nr+1 )
        newgrad1_knot1_bias = float(grad1_knot1[newgrad1_knot1_bias_nr-3:newgrad1_knot1_bias_nr])
        
        # color
        newgrad1_knot1_col_nr = grad1_knot1.find("col")
        newgrad1_knot1_col_nr2 = grad1_knot1.find("brig")
        newgrad1_knot1_col = grad1_knot1[newgrad1_knot1_col_nr+6:newgrad1_knot1_col_nr2-2]
        newgrad1_knot1_col_1komma = newgrad1_knot1_col.find(",")
        newgrad1_knot1_col_2komma = newgrad1_knot1_col.rfind(",")
        newgrad1_knot1_col_ende = newgrad1_knot1_col.find(")")
        vector_value_1 = float(newgrad1_knot1_col[11:newgrad1_knot1_col_1komma])
        vector_value_2 = float(newgrad1_knot1_col[newgrad1_knot1_col_1komma+2:newgrad1_knot1_col_2komma])
        vector_value_3 = float(newgrad1_knot1_col[newgrad1_knot1_col_2komma+2:newgrad1_knot1_col_ende])
        
        # position
        newgrad1_knot1_pos_nr = grad1_knot1.find("pos")
        newgrad1_knot1_pos = float(grad1_knot1[newgrad1_knot1_pos_nr+6:newgrad1_knot1_col_nr-2])
        
        # brightness
        newgrad1_knot1_bri_nr = len(grad1_knot1)
        newgrad1_knot1_bri = float(grad1_knot1[newgrad1_knot1_col_nr2+13:newgrad1_knot1_bri_nr])
    
    
        grad2.FlushKnots()
    
        grad2.InsertKnot(index = newgrad1_knot1_index, bias = newgrad1_knot1_bias, pos = newgrad1_knot1_pos, col = c4d.Vector(vector_value_1, vector_value_2, vector_value_3), brightness = newgrad1_knot1_bri)
    
    
        shdr2[c4d.SLA_GRADIENT_GRADIENT] =  grad2
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
        c4d.EventAdd()
    
    # Execute main()
    if __name__=='__main__':
        main()
    


  • Hi, @PdZ in which version are you, using R20 with the first code works as expected, could you share a scene example?

    Cheers,
    Maxime.



  • @PdZ any news?



  • Hi Adam,

    thx for your response!
    Sorry I was busy. Didn't meant to let you wait.

    Iam working with:
    Cinema 4D Studio R20 20.059

    Heres the testscene:
    gradient_test.c4d

    Heres the code:

    import c4d
    from c4d import gui
    
    def main():
        mat = doc.GetFirstMaterial()           #Gets the first material in the materials manager
        shdr1 = mat[c4d.MATERIAL_COLOR_SHADER]
    
        shd = c4d.BaseList2D(1011100) # Gradient
        mat[c4d.MATERIAL_DIFFUSION_SHADER] = shd
        mat.InsertShader(shd)
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
    
        shdr2 = mat[c4d.MATERIAL_DIFFUSION_SHADER]
    
    
        grad1 = shdr1[c4d.SLA_GRADIENT_GRADIENT]
        grad2 = shdr2[c4d.SLA_GRADIENT_GRADIENT]
    
    
        grad1_knot1 = grad1.GetKnot(0)
        print("Knot1 = " + str(grad1_knot1))
        grad1_knot2 = grad1.GetKnot(1)
        print("Knot2 = " + str(grad1_knot2))
        grad1_knot3 = grad1.GetKnot(2)
        print("Knot3 = " + str(grad1_knot3))
    
        index1 = grad1_knot1['index']
        print("Index" + " " + str(index1))
        index2 = grad1_knot2['index']
        print("Index" + " " + str(index2))
        index3 = grad1_knot3['index']
        print("Index" + " " + str(index3))
        pos1 = grad1_knot1['pos']
        print("Position" + " " + str(pos1))
        pos2 = grad1_knot2['pos']
        print("Position" + " " + str(pos2))
        pos3 = grad1_knot2['pos']
        print("Position" + " " + str(pos3))
        col1 = grad1_knot1['col']
        print("Color" + " " + str(col1))
        col2 = grad1_knot2['col']
        print("Color" + " " + str(col2))
        col3 = grad1_knot2['col']
        print("Color" + " " + str(col3))
        bri1 = grad1_knot1['brightness']
        print("Brightness" + " " + str(bri1))
        bri2 = grad1_knot2['brightness']
        print("Brightness" + " " + str(bri2))
        bri3 = grad1_knot2['brightness']
        print("Brightness" + " " + str(bri3))
        grad2.FlushKnots()
    
        grad2.InsertKnot(col=col1, pos=pos1,index=index1)
        grad2.InsertKnot(col=col2, pos=pos2,index=index2)
        grad2.InsertKnot(col=col3, pos=pos3,index=index3)
        shdr2[c4d.SLA_GRADIENT_GRADIENT] =  grad2
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
        c4d.EventAdd()
        
    # Execute main()
    if __name__=='__main__':
        main()
    

    Here is what I get as gradient in the Diffusion shader:
    Knots.jpg

    There are 3 Knots. 2 at the same position on the right side.
    Also the console tells me that result:
    console.jpg

    Thx in Advance!
    PdZ



  • @PdZ

    Ok adam,

    iam a stupid idiot. I had a typo.
    Pls ignore everything. I checked the code and I set values of knot 2 to knot 3.

    Iam sorry!



  • Don't feel sorry yes this is the issue and since Knot ID are not ordered from right to left but from creation order its why it's confused you.
    Moreover, using a for loop will make way more sense and help you to avoid this kind of stuff.

        grad1 = shdr1[c4d.SLA_GRADIENT_GRADIENT]
        grad2 = shdr2[c4d.SLA_GRADIENT_GRADIENT]
    
        for knotId in xrange(grad1.GetKnotCount()):
            knot = grad1.GetKnot(knotId)
            grad2.InsertKnot(col=knot['col'], pos=knot['pos'],index=knot['index'])
    
        grad2.FlushKnots()
    
        shdr2[c4d.SLA_GRADIENT_GRADIENT] =  grad2
    

    Finally, a BaseShader is derived from BaseList2D which is derived from C4DAtom that mean you can use GetClone to retrieves a clone of this shader so your code can look like.

    import c4d
    
    def main():
        mat = doc.GetFirstMaterial()
        colorShader = mat[c4d.MATERIAL_COLOR_SHADER]
        if colorShader is None:
            return
        
        copyColor = colorShader.GetClone()
        mat[c4d.MATERIAL_DIFFUSION_SHADER] = copyColor
        mat.InsertShader(copyColor)
        
        mat.Message(c4d.MSG_UPDATE)
        mat.Update(True, True)
        c4d.EventAdd()
        
    # Execute main()
    if __name__=='__main__':
        main()
    

    Cheers,
    Maxime.