Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Ipo.py « Blender « modules « python « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 110f95a5d073567e6361e0179058ea87ac247935 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
"""The Blender Ipo module

This module provides access to **Ipo** objects in Blender.

An Ipo object is a datablock of IpoCurves which control properties of
an object in time.

Note that IpoCurves assigned to rotation values (which must be specified
in radians) appear scaled in the IpoWindow (which is in fact true, due
to the fact that conversion to an internal unit of 10.0 angles happens).

Example::
  
  from Blender import Ipo, Object

  ipo = Ipo.New('Object', 'ObIpo')                   # Create object ipo with name 'ObIpo'
  curve = ipo.addCurve('LocY')                       # add IpoCurve for LocY
  curve.setInterpolation('Bezier')                   # set interpolation type
  curve.setExtrapolation('CyclicLinear')             # set extrapolation type

  curve.addBezier((0.0, 0.0))                        # add automatic handle bezier point
  curve.addBezier((20.0, 5.0), 'Free', (10.0, 4.0))  # specify left handle, right auto handle
  curve.addBezier((30.0, 1.0), 'Vect')               # automatic split handle
  curve.addBezier((100.0, 1.0))                      # auto handle

  curve.update()                                     # recalculate curve handles

  curve.eval(35.0)                                   # evaluate curve at 35.0

  ob = Object.get('Plane')
  ob.setIpo(ipo)                                     # assign ipo to object
"""

import _Blender.Ipo as _Ipo

import shadow

_RotIpoCurves = ["RotX", "RotY", "RotZ", "dRotX", "dRotY", "dRotZ"]

_radian_factor = 5.72957814 # 18.0 / 3.14159255

def _convertBPoint(b):
	f = _radian_factor
	newb = BezierPoint() 
	p = b.pt
	q = newb.pt
	q[0], q[1] = (p[0], f * p[1])
	p = b.h1
	q = newb.h1
	q[0], q[1] = (p[0], f * p[1])
	p = b.h2
	q = newb.h2
	q[0], q[1] = (p[0], f * p[1])
	return newb


class IpoBlock(shadow.shadowEx):
	"""Wrapper for Blender Ipo DataBlock

  Attributes
  
    curves -- list of owned IpoCurves
"""
	def get(self, channel = None):
		"""Returns curve with channel identifier 'channel', which is one of the properties
listed in the Ipo Window, 'None' if not found.
If 'channel' is not specified, all curves are returned in a list"""
		if channel:
			for c in self._object.curves:
				if c.name == channel:
					return IpoCurve(c)
			return None
		else:
			return map(lambda x: IpoCurve(x), self._object.curves)

	def __getitem__(self, k):
		"""Emulates dictionary syntax, e.g. ipocurve = ipo['LocX']"""
		curve = self.get(k)
		if not curve:
			raise KeyError, "Ipo does not have a curve for channel %s" % k
		return curve		

	def __setitem__(self, k, val):
		"""Emulates dictionary syntax, e.g. ipo['LocX'] = ipocurve"""
		c = self.addCurve(k, val)
		
	has_key = get # dict emulation

	items = get   # dict emulation

	def keys(self):
		return map(lambda x: x.name, self.get())

	def addCurve(self, channel, curve = None):
		"""Adds a curve of channel type 'channel' to the Ipo Block. 'channel' must be one of
the object properties listed in the Ipo Window. If 'curve' is not specified,
an empty curve is created, otherwise, the existing IpoCurve 'curve' is copied and
added to the IpoBlock 'self'.
In any case, the added curve is returned.
""" 		
		if curve:
			if curve.__class__.__name__ != "IpoCurve":
				raise TypeError, "IpoCurve expected"
			c = self._object.addCurve(channel, curve._object)

			### RotIpo conversion hack
			if channel in _RotIpoCurves:
				print "addCurve, converting", curve.name
				c.points = map(_convertBPoint, curve.bezierPoints)
			else:
				c.points = curve.bezierPoints
		else:	
			c = self._object.addCurve(channel)
		return IpoCurve(c)

	_getters = { 'curves' : get }

class BezierPoint:
	"""BezierPoint object

  Attributes
  
    pt   -- Coordinates of the Bezier point

    h1   -- Left handle coordinates

    h2   -- Right handle coordinates

    h1t  -- Left handle type (see IpoCurve.addBezier(...) )

    h2t  -- Right handle type
"""

BezierPoint = _Ipo.BezTriple # override

class IpoCurve(shadow.shadowEx):
	"""Wrapper for Blender IpoCurve

  Attributes

    bezierPoints -- A list of BezierPoints (see class BezierPoint),
    defining the curve shape
"""

	InterpolationTypes = _Ipo.InterpolationTypes
	ExtrapolationTypes = _Ipo.ExtrapolationTypes

	def __init__(self, object):
		self._object = object
		self.__dict__['bezierPoints'] = self._object.points

	def __getitem__(self, k):
		"""Emulate a sequence of BezierPoints"""
		print k, type(k)
		return self.bezierPoints[k]

	def __repr__(self):
		return "[IpoCurve %s]" % self.name

	def __len__(self):
		return len(self.bezierPoints)

	def eval(self, time):
		"""Returns float value of curve 'self' evaluated at time 'time' which
must be a float."""
		return self._object.eval(time)

	def addBezier(self, p, leftType = 'Auto', left = None, rightType = None, right = None):
		"""Adds a Bezier triple to the IpoCurve.

The following values are float tuples (x,y), denoting position of a control vertex:

p     -- The position of the Bezier point

left  -- The position of the leftmost handle

right -- The position of the rightmost handle

'leftType', 'rightType' must be one of:

"Auto"  --  automatic handle calculation. In this case, 'left' and 'right' don't need to be specified

"Vect"  --  automatic split handle calculation. 'left' and 'right' are disregarded.

"Align" --  Handles are aligned automatically. In this case, 'right' does not need to be specified.

"Free"  --  Handles can be set freely - this requires both arguments 'left' and 'right'.

"""

		b = _Ipo.BezTriple()
		b.pt[0], b.pt[1] = (p[0], p[1])
		b.h1t = leftType

		if rightType:
			b.h2t = rightType
		else:
			b.h2t = leftType

		if left:
			b.h1[0], b.h1[1] = (left[0], left[1])

		if right:	
			b.h2[0], b.h2[1] = (right[0], right[1])

		self.__dict__['bezierPoints'].append(b)
		return b

	def update(self, noconvert = 0):
		# This is an ugly fix for the 'broken' storage of Rotation
		# ipo values. The angles are stored in units of 10.0 degrees,
		# which is totally inconsistent with anything I know :-)
		# We can't (at the moment) change the internals, so we
		# apply a conversion kludge..
		if self._object.name in _RotIpoCurves and not noconvert:
			points = map(_convertBPoint, self.bezierPoints)
		else:
			points = self.bezierPoints
		self._object.points = points
		self._object.update()

	def getInterpolationType(self, ipotype):
		"Returns the Interpolation type - see also IpoCurve.InterpolationTypes"
		return self._object.getInterpolationType()
		
	def setInterpolationType(self, ipotype):
		"""Sets the interpolation type which must be one of IpoCurve.InterpolationTypes"""
		try:
			self._object.setInterpolationType(ipotype)
		except:
			raise TypeError, "must be one of %s" % self.InterpolationTypes.keys()

	def getExtrapolationType(self, ipotype):
		"Returns the Extrapolation type - see also IpoCurve.ExtrapolationTypes"
		return self._object.getExtrapolationType()

	def setExtrapolationType(self, ipotype):
		"""Sets the interpolation type which must be one of IpoCurve.ExtrapolationTypes"""
		try:
			self._object.setInterpolationType(ipotype)
		except:
			raise TypeError, "must be one of %s" % self.ExtrapolationTypes.keys()
	

def New(blocktype, name = None):
	"""Returns a new IPO block of type 'blocktype' which must be one of:
["Object", "Camera", "World", "Material"]
"""
	if name:
		i = _Ipo.New(blocktype, name)
	else:
		i = _Ipo.New(blocktype)
	return IpoBlock(i)

def Eval(ipocurve, time):  # emulation code
	"""This function is just there for compatibility. 
Use IpoCurve.eval(time) instead"""
	return ipocurve.eval(time)

def Recalc(ipocurve):  # emulation code
	"""This function is just there for compatibility. Note that Ipos
assigned to rotation values will *not* get converted to the proper
unit of radians.
In the new style API, use IpoCurve.update() instead"""
	return ipocurve.update(1)

def get(name = None):
	"""If 'name' given, the Ipo 'name' is returned if existing, 'None' otherwise.
If no name is given, a list of all Ipos is returned"""
	if name:
		ipo = _Ipo.get(name)	
		if ipo:
			return IpoBlock(ipo)
		else:
			return None
	else:
		return shadow._List(_Ipo.get(), IpoBlock)

Get = get # emulation