forked from bartvdbraak/blender
utility script for cleaning ipos animation curves,
used in YoFrankie to reduce file size for large actions
This commit is contained in:
parent
fe85bdd040
commit
48abe5a66e
192
release/scripts/animation_clean.py
Normal file
192
release/scripts/animation_clean.py
Normal file
@ -0,0 +1,192 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'Clean Animation Curves'
|
||||
Blender: 249
|
||||
Group: 'Animation'
|
||||
Tooltip: 'Remove unused keyframes for ipo curves'
|
||||
"""
|
||||
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# Copyright (C) 2008-2009: Blender Foundation
|
||||
#
|
||||
# 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,
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
import bpy
|
||||
from Blender import IpoCurve, Draw, Window
|
||||
|
||||
def clean_ipos(ipos):
|
||||
eul = 0.001
|
||||
|
||||
def isflat(vec):
|
||||
prev_y = vec[0][1]
|
||||
mid_y = vec[1][1]
|
||||
next_y = vec[2][1]
|
||||
|
||||
# flat status for prev and next
|
||||
return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul
|
||||
|
||||
|
||||
|
||||
X=0
|
||||
Y=1
|
||||
PREV=0
|
||||
MID=1
|
||||
NEXT=2
|
||||
|
||||
LEFT = 0
|
||||
RIGHT = 1
|
||||
|
||||
TOT = 0
|
||||
TOTBEZ = 0
|
||||
# for ipo in bpy.data.ipos:
|
||||
for ipo in ipos:
|
||||
if ipo.lib:
|
||||
continue
|
||||
# print ipo
|
||||
for icu in ipo:
|
||||
interp = icu.interpolation
|
||||
extend = icu.extend
|
||||
|
||||
bezierPoints = icu.bezierPoints
|
||||
bezierVecs = [bez.vec for bez in bezierPoints]
|
||||
|
||||
l = len(bezierPoints)
|
||||
|
||||
TOTBEZ += l
|
||||
|
||||
# our aim is to simplify this ipo as much as possible!
|
||||
if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR:
|
||||
#print "Not yet supported"
|
||||
|
||||
if interp == IpoCurve.InterpTypes.BEZIER:
|
||||
flats = [isflat(bez) for bez in bezierVecs]
|
||||
else:
|
||||
# A bit of a waste but fake the locations for these so they will always be flats
|
||||
# IS better then too much duplicate code.
|
||||
flats = [(True, True)] * l
|
||||
for v in bezierVecs:
|
||||
v[PREV][Y] = v[NEXT][Y] = v[MID][Y]
|
||||
|
||||
|
||||
# remove middle points
|
||||
if l>2:
|
||||
done_nothing = False
|
||||
|
||||
while not done_nothing and len(bezierVecs) > 2:
|
||||
done_nothing = True
|
||||
i = l-2
|
||||
|
||||
while i > 0:
|
||||
#print i
|
||||
#print i, len(bezierVecs)
|
||||
if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]:
|
||||
|
||||
if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul:
|
||||
done_nothing = False
|
||||
|
||||
del flats[i]
|
||||
del bezierVecs[i]
|
||||
icu.delBezier(i)
|
||||
TOT += 1
|
||||
l-=1
|
||||
i-=1
|
||||
|
||||
# remove endpoints
|
||||
if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1:
|
||||
#print l, len(bezierVecs)
|
||||
# start
|
||||
|
||||
while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)):
|
||||
print "\tremoving 1 point from start of the curve"
|
||||
del flats[0]
|
||||
del bezierVecs[0]
|
||||
icu.delBezier(0)
|
||||
TOT += 1
|
||||
l-=1
|
||||
|
||||
|
||||
# End
|
||||
while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul):
|
||||
print "\tremoving 1 point from end of the curve", l
|
||||
del flats[l-1]
|
||||
del bezierVecs[l-1]
|
||||
icu.delBezier(l-1)
|
||||
TOT += 1
|
||||
l-=1
|
||||
|
||||
|
||||
|
||||
if l==2:
|
||||
if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul:
|
||||
# remove the second point
|
||||
print "\tremoving 1 point from 2 point bez curve"
|
||||
# remove the second point
|
||||
del flats[1]
|
||||
del bezierVecs[1]
|
||||
icu.delBezier(1)
|
||||
TOT+=1
|
||||
l-=1
|
||||
|
||||
# Change to linear for faster evaluation
|
||||
'''
|
||||
if l==1:
|
||||
print 'Linear'
|
||||
icu.interpolation = IpoCurve.InterpTypes.LINEAR
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
||||
if interp== IpoCurve.InterpTypes.CONST:
|
||||
print "Not yet supported"
|
||||
|
||||
print 'total', TOT, TOTBEZ
|
||||
return TOT, TOTBEZ
|
||||
|
||||
def main():
|
||||
ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3')
|
||||
|
||||
sce = bpy.data.scenes.active
|
||||
ipos = []
|
||||
|
||||
if ret == 3:
|
||||
ipos.extend(list(bpy.data.ipos))
|
||||
else:
|
||||
for ob in sce.objects.context:
|
||||
if ret == 1:
|
||||
ipo = ob.ipo
|
||||
if ipo:
|
||||
ipos.append(ipo)
|
||||
|
||||
elif ret == 2:
|
||||
action = ob.action
|
||||
if action:
|
||||
ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo])
|
||||
|
||||
|
||||
|
||||
if not ipos:
|
||||
Draw.PupMenu('Error%t|No ipos found')
|
||||
else:
|
||||
total_removed, total = clean_ipos(ipos)
|
||||
Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points')
|
||||
|
||||
Window.RedrawAll()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user