ipo tools script - better ipo cleanup

this is a script I used while we produced this opensource game : www.powerofwill.cz

it’s a simple script which is suitable for various ipo operations, like setting interpolation and extrapolation for all curves in all ipos on all selected objects. It also features a cleaning alglofithm which is tiny bit better than the one in blender, and works for all ipos also in actions, so it is good cleaning actions after baking or after import.

enjoy

#!BPY

""" Registration info for Blender menus: <- these words are ignored
Name: 'Ipo tools'
Blender: 234
Group: 'Animation'
Tip: 'tools for batch operations on ipos of objects and armatures, also for cleaning data.'
"""
#
#===============================================#
# ipo cleanup script  by Vilem Novak            #
#                                               #
# if you have any questions about this script   #
# email me pildanovak at post dot cz            #
#                                               #
#===============================================#

# -------------------------------------------------------------------------- 
# ***** BEGIN GPL LICENSE BLOCK ***** 
# 
# This program is free software; you can redistribute it and/or 
# modify it under the terms of the GNU General Public License 
# as published by the Free Software Foundation; either version 2 
# of the License, or (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program; if not, write to the Free Software Foundation, 
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
# 
# ***** END GPL LICENCE BLOCK ***** 
# -------------------------------------------------------------------------- 


import Blender
from Blender import *
#from Blender.Armature import *
#from Blender.Armature.Bone import *
from Blender.Object import*
from Blender.Scene import *
from Blender.Mathutils import*
from Blender.NMesh import FaceModes,FaceTranspModes
print FaceModes
print FaceTranspModes

scn= Scene.GetCurrent()
ctx= scn.getRenderingContext()
theresold=Draw.Create(0.00001)
onlySlopes=Draw.Create(1)

def interface():
    global theresold,onlySlopes

    BGL.glClearColor(0.5, 0.5, 0.5, 1)
    BGL.glColor3f(1.,1.,1.)
    BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)

    ####buttons
    Draw.Button("clearIpos", 4, 110, 10, 60, 25,"clear all ipo curves in selected object's Ipos (not in actions)")
    Draw.Button("Exit", 1, 170, 10, 40, 25)
    BGL.glRasterPos2i(150,190)
    Draw.Text("set interpolation:")
    Draw.Button("Linear", 6, 150, 160, 70, 25)
    Draw.Button("Bezier", 7, 150, 130, 70, 25)
    Draw.Button("Constant", 8, 150, 100, 70, 25)

    BGL.glRasterPos2i(10,190)
    Draw.Text("set extrapolation:")
    Draw.Button("Constant", 11, 10, 170, 120, 18)
    Draw.Button("Extrapolation", 12, 10, 150, 120, 18)
    Draw.Button("Cyclic", 13, 10, 130, 120, 18)
    Draw.Button("Cyclic_extrapolation", 14, 10, 110, 120, 18)
    
    Draw.Button("CleanupIpos", 10, 10, 10, 100, 25,"Removes redundant points in the ipo curves using the theresold value (for armatures also for associated actions)")
    theresold = Blender.Draw.Number("theresold", 2, 10, 60, 210, 18, theresold.val, .0000, 10, "differences smaller than this will be cleaned")
    onlySlopes=Draw.Toggle("only slopes", 1000, 10, 40, 100, 18,onlySlopes.val,"if turned on, only points on the slopes of ipocurves will be filtered.")
    


def exit(evt, val):
    if evt == Blender.Draw.ESCKEY and not val: Blender.Draw.Exit()


def events(event):
    if event==1:
        Draw.Exit()
    if event==4:
        clearIpos()
    if event ==6:
        setType('Linear')
    if event ==7:
        setType('Bezier')
    if event ==8:
        setType('Constant')

    if event ==10:
        cleanupIpos()

    if event ==11:
        setExt('Constant')
    if event ==12:
        setExt('Extrapolation')
    if event ==13:
        setExt('Cyclic')
    if event ==14:
        setExt('Cyclic_extrapolation')
    if event==1000:
        print onlySlopes.val




def extractCurves():#get cruves from all selected objects and armatures
    obj=GetSelected()

    curves=[]
    print 'anikurvy'
    for ob in obj:
        ipo=ob.getIpo()
        if ipo!=None:
            curves.extend(ipo.getCurves())
        #print ob.getType
        if ob.getType()=='Armature':
            print 'object is an armature'
            a = ob.getAction()
            aipos = a.getAllChannelIpos()
            print aipos
            for key in aipos.keys():
                curves.extend(aipos[key].getCurves())
    print 'asponkurvy'
    return curves
    



def cleanupIpos():
    global fsold,onlySlopes
    scn= Scene.GetCurrent()

    oi=0
    curves=extractCurves()
    
    i=0
    print 'starting cleanup'
    total=0
    
    totalp=0
    
    for c in curves:
        t=theresold.val
    
        if c.name[:4]=='Quat':
            t=t/2.0####quaternions get more care in actions, since they are only from -1 to 1 representing 360 degrees
            
        points= c.bezierPoints
        erase=[]
        ##########################
        #stats
        ##########################
        beginarea=0
        arealen=0
        peaks=0
        threses=0
        lthreses=0
        ##########################
        #cleaning
        #############################
        for a in range(1,len(points)-1):
            pt=points[a].pt
            
#                pt1=points[a-1].pt
            pt1=points[beginarea].pt
            pt2=points[a+1].pt

            # the supercondition for distance from slope
            dif=abs((pt1[1]+(pt2[1]-pt1[1])*((pt[0]-pt1[0])/(pt2[0]-pt1[0])))-pt[1])
            #print dif
            thres = dif<t
            littlethres = dif<t/10###littlethres is for very small peaks on straight curves
            peak = (onlySlopes.val) and ((pt1[1]<=pt[1] and pt2[1]<=pt[1]) or (pt1[1]>=pt[1] and pt2[1]>=pt[1]))
            threses+=thres
            lthreses+=littlethres
            peaks+=peak
            if (thres and not peak) or littlethres:
                        erase.append(a)
            else:
                beginarea=a
        erase.reverse()
        total+=len(erase)
        totalp+=len(points)
        for p in erase:    
            c.delBezier(p)
        c.interpolation=IpoCurve.InterpTypes.LINEAR
        c.recalc()
    scn.update()
    
    print 'cleaned up %d out of %d points in %d curves' % (total,totalp,len(curves))
    
    Blender.Window.RedrawAll()
    
    
    
def clearIpos():
    obj=GetSelected()
    for ob in obj:
        ipo=Blender.Ipo.New('Object',ob.name)
        ob.setIpo(ipo)
    Blender.Window.RedrawAll()



def setType(type):
    curves=extractCurves()
    for c in curves:
        c.setInterpolation(type)
        c.recalc()
    Blender.Window.RedrawAll()
class emp:
    pass



def setExt(ext):

    curves=extractCurves()
    for c in curves:
        c.setExtrapolation(ext)
        c.recalc()
                #print 'e'
    Blender.Window.RedrawAll()




Draw.Register(interface,exit,events)

Thanks for this - great script

thank you for sharing/inspiration

Setting extrapolation on all selected curves is worth the price of admission for me!

Great script.
It helped me writing my new Ipo script: a converter from Global values (Loc, Rot, Scale) to relative (dLoc, dRot, dScale):

http://blenderartists.org/forum/showthread.php?p=1351865#post1351865

And let’s keep the ipo scripts coming :smiley: