SetKnot to a gradient does not work properly
On 17/03/2013 at 03:46, xxxxxxxx wrote:
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:
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
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.
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()
On 18/03/2013 at 11:01, xxxxxxxx wrote:
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.
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.
On 19/03/2013 at 14:22, xxxxxxxx wrote:
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.