Mercurial > touhou
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) |