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

    Cinema Gradient, weird behaviour

    Cinema 4D SDK
    r20 sdk python
    2
    7
    1.2k
    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.
    • P
      PdZ
      last edited by PdZ

      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

      1 Reply Last reply Reply Quote 0
      • P
        PdZ
        last edited by

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

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

          Cheers,
          Maxime.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by

            @PdZ any news?

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • P
              PdZ
              last edited by PdZ

              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

              P 1 Reply Last reply Reply Quote 0
              • P
                PdZ @PdZ
                last edited by

                @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!

                1 Reply Last reply Reply Quote 0
                • M
                  m_adam
                  last edited by m_adam

                  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.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

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