Changing Material IPO curves in Blender 2.27

I’m still learning the ins and outs of Python and Blender’s Python API, and this is driving me nuts:

I have a material with two textures. I want to change a material IPO on one texture during my animation. Currently the only IPOCurves which exist for this material are ones I created. I wrote this code:


import Blender

mat = Blender.Object.Get("hx19").getData().getMaterials()
ipos = mat[0].getIpo()
ipos[0][0].bezierPoints[0].pt=(10,0)
mat[0].setIpo(ipos)

the assignment to ipos[0][0] gives the error:

AttributeError: cannot directly assign, use slice assignment instead

I have no idea how to do a slice assignment. For the matter, even if I do know how to do it, I don’t feel this is going to change the control points.
I was able to append a BezTriple (I think that’s the type) to the list of
control points, but nothing changed in the IPO window.

Ideally I’d like to be able to create the IPO curves and assign them to the materials, but everything I’ve tried won’t allow me to create a Material IPO curve of type "Col’.

Any help would be appreciated.

Thanks – ken

You can not assign directely a tuple (10,0),
pt= (10,0)

but you can assign value to separate element:
pt[0]=10.0
pt[1]=0.0

import Blender
mat = Blender.Object.Get("hx19").getData().getMaterials()
ipos = mat[0].getIpo()
ipos[0][0].bezierPoints[0].pt[0]=10.0
ipos[0][0].bezierPoints[0].pt[1]=0.0
mat[0].setIpo(ipos)

(in blender228, there is no ipo in material…)

Ok, I should have thought to try accessing the individual elements… %|

But it still doesn’t seem to have any effect.

import Blender

mat = Blender.Object.Get("hx19").getData().getMaterials()

ipos = mat[0].getIpo()
print "was ",ipos[0][0].bezierPoints[0].pt[0]
ipos[0][0].bezierPoints[0].pt[0]=10.0
print "is  ",ipos[0][0].bezierPoints[0].pt[0]
mat[0].setIpo(ipos)

ipo2 = mat[0].getIpo()
print "still is ",ipo2[0][0].bezierPoints[0].pt[0]

gives this output:

was  51.0
is   51.0
still is  51.0

Do I need to do something else to update the material?

BTW, any idea if there will be any way to do something similar in post-2.28? I’m avoiding
2.28 right now since setEuler doesn’t seem to work (but that’s another topic).

Thanks – Ken

Ok,
try this:

import Blender
mat = Blender.Object.Get("hx19").getData().getMaterials()
ipos = mat[0].getIpo()
i= Blender.Ipo.get(ipos.name)
c=i[0]
c[0].bezierPoints[0].pt[0]=1
c[0].bezierPoints[0].pt[1]=3
print dir(ipos[0])
Blender.Ipo.Recalc(c[0])
mat[0].setIpo(ipos)
Blender.Window.RedrawAll()

A-ha! That did the trick. I’ll study this to figure out exactly what it’s doing.

Thanks so much! – Ken

2 years later and this script is out of date-
The line
i= Blender.Ipo.get(ipos.name)
Dosent work, but even the substitute from the docs stuffs up.
Could anybody update this example?

  • Cam

2 years later and this script is out of date-
The line
i= Blender.Ipo.get(ipos.name)
Dosent work, but even the substitute from the docs stuffs up.
Could anybody update this example?

  • Cam[/quote]

Here’s an updated version which works ('almost) with Version 2.36:


import Blender
                                                                                
mat = Blender.Object.Get("Plane").getData().getMaterials()
print 'Material name is "%s"'%mat[0].getName()
ipo = mat[0].getIpo()
print 'Ipo name is "%s"'%ipo.getName()
for curve in ipo.getCurves():
    if curve.name == 'Col':
        p = curve.getPoints()[0]
        print 'First point was ',p.getPoints()
        p.setPoints([p.getPoints()[0]+2,3])
        curve.Recalc()
        print 'First point is now',p.getPoints()
                                                                                
Blender.Window.RedrawAll()

This adds 2 to the x value (frame number) for the first Bezier knot of each ‘Col’ curve.

This version is a little simpler, since it uses getCurve() to specifically get one curve:


import Blender
                                                                                
mat = Blender.Object.Get("Plane").getData().getMaterials()
print 'Material name is "%s"'%mat[0].getName()
ipo = mat[0].getIpo()
print 'Ipo name is "%s"'%ipo.getName()
curveName='R'
try:
    curve = ipo.getCurve(curveName)
    p = curve.getPoints()[0]
    print 'First point is ',p.getPoints()
    p.setPoints([p.getPoints()[0]+2,3])
    curve.Recalc()
    print 'First point is now',p.getPoints()
except:
    print 'no IPO curve named "%s" exists'%curveName
                                                                                
Blender.Window.RedrawAll()

Now, the question I have (since I’ve also discovered the old way doesn’t work) is how does one distinguish between the various IPO curves and set the bezTriple points directly? I specifically have two textures assigned to one material and in the UI I can define a Col IPO (to control the MapTo Color value). But the Python API seems to have two deficiencies with textures:
(1) if I use getCurves() to return all curves, I get two ‘Col’ curves. They have the same name, and the order hey appear in the list returned depends on the order in which they are defined, not on the order of the textures in the materials list.
(2) if I use getCurve(‘Col’) to retrive the curve, it returns only the first Col curve I defined

Also, how the heck can I define a bezTriple? I can use setPoint() to define the xy position of the knot, but what if I want to set the values for the handles?