SetKnot to a gradient does not work properly

On 17/03/2013 at 03:46, xxxxxxxx wrote:

Hi,
i am new to phyton and have a problem regarding the gradient of a material.
I would like to control the knots as shown below but it does not work.
I found a post similar to my problem and tried the adviceses from there but it does not work.

This is my code:

import c4d

def main() :

#this routine shall adjust every other knots position depending on the position of the
  #knot before and a  customer value so that the distance of Knot 0 to 1, 2 to 3 etc. ist always the same 
  #a gradient with knots does already exist

mat = doc.GetFirstMaterial()           #Gets the first material in the materials manager
  shdr = mat[c4d.MATERIAL_COLOR_SHADER]  #The shader inside the "texture" option
  grad = shdr[c4d.SLA_GRADIENT_GRADIENT] #Get the gradient GUI and assign it to a variable
  step = 0.2

knots_count = grad.GetKnotCount()                #How many knots are there?
  if knots_count > 1:                              #if more then 1 knot...
      for i in range(0, knots_count,2) :            #for every other knot (begin with 0)
                                
          knots_pos = grad.GetKnot(i)              #get the "dict" values like index, pos, bias etc.
          position = knots_pos["pos"]              #get only the position value
        
          grad.SetKnot(index=i+1, pos=position+step) #set the new position for every second knot does not work
          shdr[c4d.SLA_GRADIENT_GRADIENT] = grad     #write the value back to the system

shdr[c4d.SLA_GRADIENT_GRADIENT] = grad #Update the gradient data
  mat.Message(c4d.MSG_UPDATE )           #Update the material changes
  mat.Update( True, True )               #Update the material's icon image

c4d.EventAdd()                         #Update C4D so things update quickly

if __name__=='__main__':
  main()

I cannot set the new position, the knot always jumps to the 0 position. Moreover it seams that i cannot change the first knot witch has the index 0 as far as i know.
Any ideas?

Thanks, CoffeeCup

On 17/03/2013 at 08:09, xxxxxxxx wrote:

I went through this same thing some time ago.
These are my notes on the subject gained from talking with Maxon support:

-To edit a Gradient data (color knots, interpolation, mode etc.) it needs to be reassigned completely  
We cannot simply move color knots(only their handles). So to change them we have to delete them using Flush  
Then re-create them from scratch again with the new position & color data  
  
-It's only possible to get/set the gradient data with GetData() & SetData().  
 So to retrieve the gradient interpolation we have to call: gradient.GetData(c4d.GRADIENT_INTERPOLATION)  
 Which is c4d.GRADIENT_INTERPOLATION_SMOOTHKNOT by default (see customgui_gradient.h).

And here is a working example script that shows how to create your own knots changes

#This is an example of changing an existing gradient in a material  
  
import c4d  
  
def main() :  
  
  # First we get the material we want to work with  
  
  mat = doc.GetFirstMaterial()           #Gets the first material in the materials manager  
  color = c4d.DescLevel(c4d.MATERIAL_COLOR_COLOR, c4d.DTYPE_COLOR)#The material's color channel  
  
  
  # Now lets grab the gradient(also known as "Xs**gradient") that is already there in the color channel  
  # We are not creating that gradient with code in this example..So it needs to be there already  
  
  shdr = mat[c4d.MATERIAL_COLOR_SHADER]  #The shader inside the "texture" option  
  shdr[c4d.SLA_GRADIENT_TYPE]= 2000      #The "Type" option...ID's are found in the xs**gradient.h file  
  shdr[c4d.SLA_GRADIENT_CYCLE] = True    #The "Cycle" option  
  shdr[c4d.SLA_GRADIENT_TURBULENCE]=0    #The "Turbulence" option  
  shdr[c4d.SLA_GRADIENT_SPACE]= 2021     #The "Space" option...ID's are found in the xs**gradient.h file  
  
  
  # Now lets drill into the gradient shader to control the knots, interpolation, and color bar  
  
  grad = shdr[c4d.SLA_GRADIENT_GRADIENT] #Get the gradient GUI and assign it to a variable   
  grad.FlushKnots()                      #Delete all existing knots  
  k1 = grad.InsertKnot(col=c4d.Vector(0.5, 0.1, 0.0), pos=0.0,index = 0)  #Gets the first knot  
  k2 = grad.InsertKnot(col=c4d.Vector(1.0 , 1.0, 1.0), pos=1.0,index= 1)  #Gets the second knot  
  
  k1 = grad.GetKnot(k1)  #Get the first knot so we can read it's dictionary values  
  k1pos = k1['pos']      #The position of the knot from the dict value 'pos'  
  k1col = k1['col']      #The color of the knot from the dict value 'col'  
        
  k2 = grad.GetKnot(k2)  #Get the second knot so we can read it's dictionary values  
  k2pos = k2['pos']      #The position of the knot from the dict value 'pos'  
  k2col = k2['col']      #The color of the knot from the dict value 'col'  
    
  k3 = grad.InsertKnot(col=k1col+k2col/2, pos=k1pos+k2pos/2) #Create a new knot using the other knot's values  
  
  
  
# Now lets change the position of the first knot's handle(diamond shape attribute) to this new value  
  
  k1pos = 0.3              
  grad.SetKnot(index=0,pos=k1pos)        #Set the handle to this new value  
  
  grad.SetData(c4d.GRADIENT_INTERPOLATION, c4d.GRADIENT_INTERPOLATION_CUBICKNOT) #Change the interpolation  
  
  shdr[c4d.SLA_GRADIENT_GRADIENT] = grad #Update the gradient data we changed  
  mat.Message(c4d.MSG_UPDATE )           #Update the material changes  
  mat.Update( True, True )               #Update the material's icon image        
  
  c4d.EventAdd()                         #Update C4D so things update quickly  
  
if __name__=='__main__':  
  main()

-ScottA

On 18/03/2013 at 11:01, xxxxxxxx wrote:

Thanks, Scott.

Well, i am still not sure what to do.
Do i have to delete all knots, then insert the new ones with InsertKnot and then change the knots attributes with SetKnots? I am only interested in the position of the knots.

CoffeeCup

On 18/03/2013 at 12:12, xxxxxxxx wrote:

Yes. That should work.

You can get the existing knots by their index numbers and save their vector positions into variables or your own list.
Then you flush all the existing knots and create new ones.
Then you set their 'pos' values using the previously saved vectors.

-ScottA

On 19/03/2013 at 14:22, xxxxxxxx wrote:

Hi, Scott,

i think i get it.
Simply by inserting the knots with InsertKnot. But i am still not sure what SetKnot does acctually - i don't need it.  But who cares, it works.

Thanks
CoffeeCup