#!/usr/bin/python
# Copyright (C) 2006 Branko Kokanovic
#
# DirectorBean.py: class which stores an animation
#
import os, sys, copy, math
from xml.sax import make_parser
from xml.sax.handler import ContentHandler
import fracttypes, fractal
# FIXME
sys.path.append("..")
from fract4dgui import preferences
#interpolation type constants
INT_LINEAR= 0
INT_LOG= 1
INT_INVLOG= 2
INT_COS= 3
def getAttrOrDefault(attrs, name, default):
x = attrs.get(name)
if x == None:
x = default
return x
def getAttrOrElse(attrs, name):
x = attrs.get(name)
if x == None:
raise ValueError(
"Invalid file: Cannot find required attribute '%s'" % name)
return x
class KeyFrame:
def __init__(self,filename,duration,stop,int_type,flags=(0,0,0,0,0,0)):
self.filename = filename
self.duration = duration
self.stop = stop
self.int_type = int_type
self.flags = flags
def save(self,fh):
fh.write(
'\t\t\n')
def load_from_xml(attrs):
kf = KeyFrame(
getAttrOrElse(attrs,"filename"),
int(getAttrOrElse(attrs,"duration")),
int(getAttrOrElse(attrs,"stop")),
int(getAttrOrElse(attrs,"inttype")),
(int(getAttrOrDefault(attrs,"xy",0)),
int(getAttrOrDefault(attrs,"xz",0)),
int(getAttrOrDefault(attrs,"xw",0)),
int(getAttrOrDefault(attrs,"yz",0)),
int(getAttrOrDefault(attrs,"yw",0)),
int(getAttrOrDefault(attrs,"zw",0))))
return kf
load_from_xml=staticmethod(load_from_xml)
class T:
def __init__(self, compiler):
self.compiler = compiler
self.reset()
def reset(self):
self.avi_file=""
self.width=640
self.height=480
self.framerate=25
self.redblue=True
#keyframes is a list of KeyFrame objects
self.keyframes=[]
def get_fct_enabled(self):
return preferences.userPrefs.getboolean("director","fct_enabled")
def set_fct_enabled(self,fct_enabled):
if fct_enabled:
preferences.userPrefs.set("director","fct_enabled","1")
else:
preferences.userPrefs.set("director","fct_enabled","0")
def get_fct_dir(self):
return preferences.userPrefs.get("director","fct_dir")
def set_fct_dir(self,dir):
preferences.userPrefs.set("director","fct_dir",dir)
def get_png_dir(self):
return preferences.userPrefs.get("director","png_dir")
def set_png_dir(self,dir):
preferences.userPrefs.set("director","png_dir",dir)
def get_avi_file(self):
return self.avi_file
def set_avi_file(self,file):
if file!=None:
self.avi_file=file
else:
self.avi_file=""
def get_width(self):
return self.width
def set_width(self,width):
if width!=None:
self.width=int(width)
else:
self.width=640
def get_height(self):
return self.height
def set_height(self,height):
if height!=None:
self.height=int(height)
else:
self.height=480
def get_framerate(self):
return self.framerate
def set_framerate(self,fr):
if fr!=None:
self.framerate=int(fr)
else:
self.framerate=25
def get_redblue(self):
return self.redblue
def set_redblue(self,rb):
if rb!=None:
if rb==1:
self.redblue=True
elif rb==0:
self.redblue=False
self.redblue=rb
else:
self.redblue=True
def add_keyframe(self,filename,duration,stop,int_type,index=None):
kf = KeyFrame(filename,duration,stop,int_type)
if index==None:
self.keyframes.append(kf)
else:
self.keyframes.insert(index, kf)
def remove_keyframe(self,index):
self.keyframes[index:index+1]=[]
def change_keyframe(self,index,duration,stop,int_type):
if index\n')
fh.write("\n")
fh.write('\t\n')
for kf in self.keyframes:
kf.save(fh)
fh.write('\t\n')
fh.write('\t\n'%
(self.avi_file,self.framerate,self.width,self.height,self.redblue))
fh.write("\n")
fh.close()
#leftover from debugging purposes
def pr(self):
print self.__dict__
def get_image_filename(self,n):
"The filename of the image containing the Nth frame"
return os.path.join(self.get_png_dir(),"image_%07d.png" %n)
def get_fractal_filename(self,n):
"The filename of the .fct file which generates the Nth frame"
return os.path.join(self.get_fct_dir(),"file_%07d.fct" % n)
def get_mu(self, int_type, x):
if int_type==INT_LINEAR:
mu=x
elif int_type==INT_LOG:
mu=math.log(x+1,2)
elif int_type==INT_INVLOG:
mu=(math.exp(x)-1)/(math.e-1)
elif int_type==INT_COS:
mu=(1-math.cos(x*math.pi))/2
else:
raise ValueError("Unknown interpolation type %d" % int_type)
return mu
# create a list containing all the filenames of the frames
def create_list(self):
framelist = []
folder_png=self.get_png_dir()
current=1
for i in range(self.keyframes_count()):
for j in range(self.get_keyframe_stop(i)): #output keyframe 'stop' times
framelist.append(self.get_image_filename(current-1))
if i < self.keyframes_count()-1:
# final frame has no transitions following it
for j in range(self.get_keyframe_duration(i)): #output all transition files
framelist.append(self.get_image_filename(current))
current=current+1
return framelist
def get_keyframe_durations(self):
durations = []
for i in xrange(self.keyframes_count()):
durations.append(self.get_keyframe_duration(i))
return durations
def get_total_frames(self):
count = 0
nframes = self.keyframes_count()
for i in xrange(nframes):
count += self.get_keyframe_stop(i)
if i < nframes - 1:
# don't count the last frame's duration
count += self.get_keyframe_duration(i)
return count
class AnimationHandler(ContentHandler):
def __init__(self,animation):
self.animation=animation
def startElement(self, name, attrs):
if name=="output":
self.animation.set_avi_file(attrs.get("filename"))
self.animation.set_framerate(attrs.get("framerate"))
self.animation.set_width(attrs.get("width"))
self.animation.set_height(attrs.get("height"))
self.animation.set_redblue(int(attrs.get("swap")))
elif name=="keyframe":
kf= KeyFrame.load_from_xml(attrs)
self.animation.keyframes.append(kf)
return