comparison 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
comparison
equal deleted inserted replaced
436:cb5c68598ab0 437:d778db08190f
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details. 12 ## GNU General Public License for more details.
13 ## 13 ##
14 14
15 from libc.stdlib cimport malloc, free
15 16
16 class Interpolator(object): 17
17 __slots__ = ('values', 'start_values', 'end_values', 'start_frame', 'end_frame', '_frame', '_formula') 18 cdef class Interpolator:
18 def __init__(self, values=(), start_frame=0, end_values=(), end_frame=0, formula=None): 19 def __init__(self, tuple values, unsigned long start_frame=0, tuple end_values=None,
19 self.values = tuple(values) 20 unsigned long end_frame=0, formula=None):
20 self.start_values = tuple(values) 21 self._length = len(values)
21 self.end_values = tuple(end_values) 22 self._values = <double*>malloc(self._length * sizeof(double))
23 self.start_values = <double*>malloc(self._length * sizeof(double))
24 self.end_values = <double*>malloc(self._length * sizeof(double))
25 for i in xrange(self._length):
26 self._values[i] = values[i]
27 self.start_values[i] = self._values[i]
28 if end_values is not None:
29 for i in xrange(self._length):
30 self.end_values[i] = end_values[i]
22 self.start_frame = start_frame 31 self.start_frame = start_frame
23 self.end_frame = end_frame 32 self.end_frame = end_frame
24 self._frame = 0 33 self._frame = 0
25 self._formula = formula or (lambda x: x) 34 self._formula = formula
35
36
37 def __dealloc__(self):
38 free(self.end_values)
39 free(self.start_values)
40 free(self._values)
41
42
43 property values:
44 def __get__(self):
45 return tuple([self._values[i] for i in xrange(self._length)])
26 46
27 47
28 def __nonzero__(self): 48 def __nonzero__(self):
29 return self._frame < self.end_frame 49 return self._frame < self.end_frame
30 50
31 51
32 def set_interpolation_start(self, frame, values): 52 cpdef set_interpolation_start(self, unsigned long frame, tuple values):
33 self.start_values = tuple(values) 53 for i in xrange(self._length):
54 self.start_values[i] = values[i]
34 self.start_frame = frame 55 self.start_frame = frame
35 56
36 57
37 def set_interpolation_end(self, frame, values): 58 cpdef set_interpolation_end(self, unsigned long frame, tuple values):
38 self.end_values = tuple(values) 59 for i in xrange(self._length):
60 self.end_values[i] = values[i]
39 self.end_frame = frame 61 self.end_frame = frame
40 62
41 63
42 def set_interpolation_end_frame(self, end_frame): 64 cpdef set_interpolation_end_frame(self, unsigned long end_frame):
43 self.end_frame = end_frame 65 self.end_frame = end_frame
44 66
45 67
46 def set_interpolation_end_values(self, values): 68 cpdef set_interpolation_end_values(self, tuple values):
47 self.end_values = tuple(values) 69 for i in xrange(self._length):
70 self.end_values[i] = values[i]
48 71
49 72
50 def update(self, frame): 73 cpdef update(self, unsigned long frame):
74 cdef double coeff
75
51 self._frame = frame 76 self._frame = frame
52 if frame >= self.end_frame - 1: #XXX: skip the last interpolation step 77 if frame + 1 >= self.end_frame: #XXX: skip the last interpolation step
53 # This bug is replicated from the original game 78 # This bug is replicated from the original game
54 self.values = self.end_values 79 for i in xrange(self._length):
55 self.start_values = self.end_values 80 self._values[i] = self.end_values[i]
81 self.start_values[i] = self.end_values[i]
56 self.start_frame = frame 82 self.start_frame = frame
57 else: 83 else:
58 coeff = self._formula(float(frame - self.start_frame) / float(self.end_frame - self.start_frame)) 84 coeff = float(frame - self.start_frame) / float(self.end_frame - self.start_frame)
59 self.values = [start_value + coeff * (end_value - start_value) 85 if self._formula is not None:
60 for (start_value, end_value) in zip(self.start_values, self.end_values)] 86 coeff = self._formula(coeff)
61 87 for i in xrange(self._length):
88 start_value = self.start_values[i]
89 end_value = self.end_values[i]
90 self._values[i] = start_value + coeff * (end_value - start_value)