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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/python/modules/Blender/Ipo.py')
-rw-r--r--intern/python/modules/Blender/Ipo.py279
1 files changed, 279 insertions, 0 deletions
diff --git a/intern/python/modules/Blender/Ipo.py b/intern/python/modules/Blender/Ipo.py
new file mode 100644
index 00000000000..110f95a5d07
--- /dev/null
+++ b/intern/python/modules/Blender/Ipo.py
@@ -0,0 +1,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