[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20389] trunk/blender/release/scripts/ animation_clean.py: utility script for cleaning ipos animation curves,

Campbell Barton ideasman42 at gmail.com
Mon May 25 02:30:06 CEST 2009


Revision: 20389
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20389
Author:   campbellbarton
Date:     2009-05-25 02:30:06 +0200 (Mon, 25 May 2009)

Log Message:
-----------
utility script for cleaning ipos animation curves,
used in YoFrankie to reduce file size for large actions

Added Paths:
-----------
    trunk/blender/release/scripts/animation_clean.py

Added: trunk/blender/release/scripts/animation_clean.py
===================================================================
--- trunk/blender/release/scripts/animation_clean.py	                        (rev 0)
+++ trunk/blender/release/scripts/animation_clean.py	2009-05-25 00:30:06 UTC (rev 20389)
@@ -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()





More information about the Bf-blender-cvs mailing list