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.059Heres the testscene:
gradient_test.c4dHeres 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:
There are 3 Knots. 2 at the same position on the right side.
Also the console tells me that result:
Thx in Advance!
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.