Mercurial > touhou
diff pytouhou/utils/interpolator.pyx @ 437:d778db08190f
Make Interpolator an extension type.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Wed, 07 Aug 2013 11:34:44 +0200 |
parents | fab7ad2f0d8b |
children | e15672733c93 |
line wrap: on
line diff
--- a/pytouhou/utils/interpolator.pyx +++ b/pytouhou/utils/interpolator.pyx @@ -12,50 +12,79 @@ ## GNU General Public License for more details. ## +from libc.stdlib cimport malloc, free -class Interpolator(object): - __slots__ = ('values', 'start_values', 'end_values', 'start_frame', 'end_frame', '_frame', '_formula') - def __init__(self, values=(), start_frame=0, end_values=(), end_frame=0, formula=None): - self.values = tuple(values) - self.start_values = tuple(values) - self.end_values = tuple(end_values) + +cdef class Interpolator: + def __init__(self, tuple values, unsigned long start_frame=0, tuple end_values=None, + unsigned long end_frame=0, formula=None): + self._length = len(values) + self._values = <double*>malloc(self._length * sizeof(double)) + self.start_values = <double*>malloc(self._length * sizeof(double)) + self.end_values = <double*>malloc(self._length * sizeof(double)) + for i in xrange(self._length): + self._values[i] = values[i] + self.start_values[i] = self._values[i] + if end_values is not None: + for i in xrange(self._length): + self.end_values[i] = end_values[i] self.start_frame = start_frame self.end_frame = end_frame self._frame = 0 - self._formula = formula or (lambda x: x) + self._formula = formula + + + def __dealloc__(self): + free(self.end_values) + free(self.start_values) + free(self._values) + + + property values: + def __get__(self): + return tuple([self._values[i] for i in xrange(self._length)]) def __nonzero__(self): return self._frame < self.end_frame - def set_interpolation_start(self, frame, values): - self.start_values = tuple(values) + cpdef set_interpolation_start(self, unsigned long frame, tuple values): + for i in xrange(self._length): + self.start_values[i] = values[i] self.start_frame = frame - def set_interpolation_end(self, frame, values): - self.end_values = tuple(values) + cpdef set_interpolation_end(self, unsigned long frame, tuple values): + for i in xrange(self._length): + self.end_values[i] = values[i] self.end_frame = frame - def set_interpolation_end_frame(self, end_frame): + cpdef set_interpolation_end_frame(self, unsigned long end_frame): self.end_frame = end_frame - def set_interpolation_end_values(self, values): - self.end_values = tuple(values) + cpdef set_interpolation_end_values(self, tuple values): + for i in xrange(self._length): + self.end_values[i] = values[i] - def update(self, frame): + cpdef update(self, unsigned long frame): + cdef double coeff + self._frame = frame - if frame >= self.end_frame - 1: #XXX: skip the last interpolation step + if frame + 1 >= self.end_frame: #XXX: skip the last interpolation step # This bug is replicated from the original game - self.values = self.end_values - self.start_values = self.end_values + for i in xrange(self._length): + self._values[i] = self.end_values[i] + self.start_values[i] = self.end_values[i] self.start_frame = frame else: - coeff = self._formula(float(frame - self.start_frame) / float(self.end_frame - self.start_frame)) - self.values = [start_value + coeff * (end_value - start_value) - for (start_value, end_value) in zip(self.start_values, self.end_values)] - + coeff = float(frame - self.start_frame) / float(self.end_frame - self.start_frame) + if self._formula is not None: + coeff = self._formula(coeff) + for i in xrange(self._length): + start_value = self.start_values[i] + end_value = self.end_values[i] + self._values[i] = start_value + coeff * (end_value - start_value)