diff options
Diffstat (limited to 'intern/python/modules/Blender')
-rw-r--r-- | intern/python/modules/Blender/BGL.py | 1 | ||||
-rw-r--r-- | intern/python/modules/Blender/Camera.py | 106 | ||||
-rw-r--r-- | intern/python/modules/Blender/Draw.py | 1 | ||||
-rw-r--r-- | intern/python/modules/Blender/Image.py | 52 | ||||
-rw-r--r-- | intern/python/modules/Blender/Ipo.py | 279 | ||||
-rw-r--r-- | intern/python/modules/Blender/Lamp.py | 168 | ||||
-rw-r--r-- | intern/python/modules/Blender/Material.py | 251 | ||||
-rw-r--r-- | intern/python/modules/Blender/Mesh.py | 250 | ||||
-rw-r--r-- | intern/python/modules/Blender/NMesh.py | 192 | ||||
-rw-r--r-- | intern/python/modules/Blender/Object.py | 391 | ||||
-rw-r--r-- | intern/python/modules/Blender/Scene.py | 143 | ||||
-rw-r--r-- | intern/python/modules/Blender/Text.py | 57 | ||||
-rw-r--r-- | intern/python/modules/Blender/Types.py | 1 | ||||
-rw-r--r-- | intern/python/modules/Blender/Window.py | 65 | ||||
-rw-r--r-- | intern/python/modules/Blender/World.py | 157 | ||||
-rw-r--r-- | intern/python/modules/Blender/__init__.py | 23 | ||||
-rw-r--r-- | intern/python/modules/Blender/shadow.py | 195 | ||||
-rw-r--r-- | intern/python/modules/Blender/sys.py | 20 |
18 files changed, 2352 insertions, 0 deletions
diff --git a/intern/python/modules/Blender/BGL.py b/intern/python/modules/Blender/BGL.py new file mode 100644 index 00000000000..033b3560e4f --- /dev/null +++ b/intern/python/modules/Blender/BGL.py @@ -0,0 +1 @@ +from _Blender.BGL import * diff --git a/intern/python/modules/Blender/Camera.py b/intern/python/modules/Blender/Camera.py new file mode 100644 index 00000000000..33f615fc0da --- /dev/null +++ b/intern/python/modules/Blender/Camera.py @@ -0,0 +1,106 @@ +"""The Blender Camera module + +This module provides access to **Camera** objects in Blender + +Example:: + + from Blender import Camera, Object, Scene + c = Camera.New('ortho') # create new ortho camera data + c.lens = 35.0 # set lens value + cur = Scene.getCurrent() # get current Scene + ob = Object.New('Camera') # make camera object + ob.link(c) # link camera data with this object + cur.link(ob) # link object into scene + cur.setCurrentCamera(ob) # make this camera the active +""" + +import shadow +import _Blender.Camera as _Camera + + +class Camera(shadow.hasIPO): + """Wrapper for Camera DataBlock + + Attributes + + lens -- The lens value + + clipStart -- The clipping start of the view frustum + + clipEnd -- The end clipping plane of the view frustum + + type -- The camera type: + 0: perspective camera, + 1: orthogonal camera - (see Types) + + mode -- Drawing mode; see Modes +""" + + _emulation = {'Lens' : "lens", + 'ClSta' : "clipStart", + 'ClEnd' : "clipEnd", + } + + Types = {'persp' : 0, + 'ortho' : 1, + } + + Modes = {'showLimits' : 1, + 'showMist' : 2, + } + + def __init__(self, object): + self._object = object + + def getType(self): + """Returns camera type: "ortho" or "persp" """ + if self.type == self.Types['ortho']: + return 'ortho' + else: + return 'persp' + + def setType(self, type): + """Sets Camera type to 'type' which must be one of ["persp", "ortho"]""" + self._object.type = self.Types[type] + + def setMode(self, *modes): + """Sets Camera modes *the nice way*, instead of direct access +of the 'mode' member. +This function takes a variable number of string arguments of the types +listed in self.Modes. + + +Example:: + + c = Camera.New() + c.setMode('showMist', 'showLimits') +""" + flags = 0 + try: + for a in modes: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of %s" % self.Modes.keys() + self.mode = flags + + def __repr__(self): + return "[Camera \"%s\"]" % self.name + +def New(type = 'persp'): + """Creates new camera Object and returns it. 'type', if specified, +must be one of Types""" + cam = Camera(_Camera.New()) + cam.setType(type) + return cam + +def get(name = None): + """Returns the Camera with name 'name', if given. Otherwise, a list +of all Cameras is returned""" + if name: + return Camera(_Camera.get(name)) + else: + return shadow._List(_Camera.get(), Camera) + +Get = get # emulation + + diff --git a/intern/python/modules/Blender/Draw.py b/intern/python/modules/Blender/Draw.py new file mode 100644 index 00000000000..6c2cb8be09f --- /dev/null +++ b/intern/python/modules/Blender/Draw.py @@ -0,0 +1 @@ +from _Blender.Draw import * diff --git a/intern/python/modules/Blender/Image.py b/intern/python/modules/Blender/Image.py new file mode 100644 index 00000000000..c1737e1bb0d --- /dev/null +++ b/intern/python/modules/Blender/Image.py @@ -0,0 +1,52 @@ +"""The Blender Image module + + This module provides (yet) basic support for Blender *Image* data blocks + + Example:: + + from Blender import Image + im = Image.Load('dead-parrot.jpg') +""" + +import _Blender.Image as _Image +import shadow + +class Image(shadow.shadow): + """Image DataBlock object + + See above example on how to create instances of Image objects. + + Attributes + + xrep -- Texture image tiling factor (subdivision) in X + + yrep -- Texture image tiling factor (subdivision) in Y + + LATER: + + * Image buffer access + + * better loading / saving of images +""" + pass + +def get(name): + """If 'name' given, the Image 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Images is returned""" + pass + +def Load(filename): + """Returns image from file 'filename' as Image object if found, 'None' else.""" + pass + +def New(name): + """This function is currently not implemented""" + pass + +# override all functions again, the above classes are just made +# for documentation + +get = _Image.get +Get = get +Load = _Image.Load + 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 diff --git a/intern/python/modules/Blender/Lamp.py b/intern/python/modules/Blender/Lamp.py new file mode 100644 index 00000000000..ab7ed63592a --- /dev/null +++ b/intern/python/modules/Blender/Lamp.py @@ -0,0 +1,168 @@ +"""The Blender Lamp module + +This module provides control over **Lamp** objects in Blender. + +Example:: + + from Blender import Lamp + l = Lamp.New('Spot') + l.setMode('square', 'shadow') + ob = Object.New('Lamp') + ob.link(l) +""" + +import _Blender.Lamp as _Lamp +import shadow + +_validBufferSizes = [512, 768, 1024, 1536, 2560] + +def _setBufferSize(self, bufsize): + """Set the lamp's buffersize. This function makes sure that a valid +bufferSize value is set (unlike setting lamp.bufferSize directly)""" + if bufsize not in _validBufferSizes: + print """Buffer size should be one of: +%s +Setting to default 512""" % _validBufferSizes + bufsize = 512 + self._object.bufferSize = bufsize + +class Lamp(shadow.hasIPO, shadow.hasModes): + """Wrapper for Blender Lamp DataBlock + + Attributes + + mode -- Lamp mode value - see EditButtons. Do not access directly + See setMode() + + type -- Lamp type value - see EditButtons. No direct access, please. + See setType() + + col -- RGB vector (R, G, B) of lamp colour + + energy -- Intensity (float) + + dist -- clipping distance of a spot lamp or decay range + + spotSize -- float angle (in degrees) of spot cone + (between 0.0 and 180.0) + + spotBlend -- value defining the blurriness of the spot edge + + haloInt -- Halo intensity + + clipStart -- shadow buffer clipping start + + clipStart -- shadow buffer clipping end + + bias -- The bias value for the shadowbuffer routine + + softness -- The filter value for the shadow blurring + + samples -- Number of samples in shadow calculation - the + larger, the better + + bufferSize -- Size of the shadow buffer which should be one of: + [512, 768, 1024, 1536, 2560] + + haloStep -- Number of steps in halo calculation - the smaller, the + the better (and slower). A value of 0 disables shadow + halo calculation + """ + + _emulation = {'Energ' : "energy", + 'SpoSi' : "spotSize", + 'SpoBl' : "SpotBlend", + 'HaInt' : "haloInt", + 'Dist' : "dist", + 'Quad1' : "quad1", + 'Quad2' : "quad2", + } + + _setters = {'bufferSize' : _setBufferSize} + + t = _Lamp.Types + + Types = {'Lamp' : t.LOCAL, + 'Spot' : t.SPOT, + 'Sun' : t.SUN, + 'Hemi' : t.HEMI, + } + + t = _Lamp.Modes + + Modes = {'quad' : t.QUAD, + 'sphere' : t.SPHERE, + 'shadow' : t.SHAD, + 'halo' : t.HALO, + 'layer' : t.LAYER, + 'negative' : t.NEG, + 'onlyShadow' : t.ONLYSHADOW, + 'square' : t.SQUARE, + } + + del t + + def __repr__(self): + return "[Lamp \"%s\"]" % self.name + + def setType(self, name): + """Set the Lamp type of Lamp 'self'. 'name' must be a string of: + +* 'Lamp': A standard point light source + +* 'Spot': A spot light + +* 'Sun' : A unidirectional light source, very far away (like a Sun!) + +* 'Hemi': A diffuse hemispherical light source (daylight without sun)""" + + try: + self._object.type = self.Types[name] + except: + raise TypeError, "type must be one of %s" % self.Types.keys() + + def getType(self): + """Returns the lamp's type as string. See setType()""" + for k in self.Types.keys(): + if self.Types[k] == self.type: + return k + + def getMode(self): + """Returns the Lamp modes as a list of strings""" + return shadow._getModeBits(self.Modes, self._object.mode) + + def setMode(self, *args): + """Set the Lamp mode of Lamp 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes. + + Example:: + + l = Lamp.New() + l.setMode('quad', 'shadow') +""" + print args + self._object.mode = shadow._setModeBits(self.Modes, args) + + def getBufferSize(self): + return self.bufferSize + +def New(type = "Lamp", name = "Lamp"): + """Returns a new Lamp datablock of type 'type' and optional name 'name' +""" + t = Lamp.Types[type] + rawlamp = _Lamp.New() + rawlamp.type = t + rawlamp.name = name + return Lamp(rawlamp) + + +def get(name = None): + """If 'name' given, the Lamp 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Lamps is returned""" + + if name: + return Lamp(_Lamp.get(name)) + else: + return shadow._List(_Lamp.get(), Lamp) + +Types = _Lamp.Types diff --git a/intern/python/modules/Blender/Material.py b/intern/python/modules/Blender/Material.py new file mode 100644 index 00000000000..f24541f0f03 --- /dev/null +++ b/intern/python/modules/Blender/Material.py @@ -0,0 +1,251 @@ +"""The Blender Material module + + This module provides access to *Material* datablocks + + Example:: + + from Blender import Material, NMesh, Object, Scene + m = Material.New() # create free Material datablock + m.rgbCol = (1.0, 0.0, 0.3) # assign RGB values + mesh = NMesh.GetRaw() # get new mesh + mesh.addMaterial(m) # add material to mesh + object = Object.New('Mesh') # create new object + object.link(mesh) # link mesh data to object + Scene.getCurrent().link(ob) # link object to current scene +""" + +import _Blender.Material as _Material +import shadow +#import Blender.Curve as Curve + +# These are getters and setters needed for emulation + +def _getRGB(obj): + return (obj.R, obj.G, obj.B) + +def _getSpec(obj): + return (obj.specR, obj.specG, obj.specB) + +def _getMir(obj): + return (obj.mirR, obj.mirG, obj.mirB) + +def _setRGB(obj, rgb): + obj.R, obj.G, obj.B = rgb + +def _setSpec(obj, rgb): + obj.specR, obj.specG, obj.specB = rgb + +def _setMir(obj, rgb): + obj.mirR, obj.mirG, obj.mirB = rgb + + + +class Material(shadow.hasIPO, shadow.hasModes): + """Material DataBlock object + + See example in the Material module documentation on how to create + an instance of a Material object. + + Attributes + + The following attributes are colour vectors (r, g, b) + + rgbCol -- The color vector (R, G, B). + The RGB values can be accessed individually as .R, .G and .B + + specCol -- Specularity color vector (specR, specG, specG) + + mirCol -- Mirror color vector (mirR, mirG, mirB) + + The following are float values: + + alpha -- The transparency + + ref -- Reflectivity float value + + emit -- Emit intensity value + + amb -- Ambient intensity value + + spec -- specularity value + + specTransp -- Specular transpareny + + haloSize -- Halo size + + mode -- The material mode bit vector - see Material.ModeFlags + + hard -- The hardness value + +""" + + _emulation = {'Mode' : "mode", + 'Ref' : "ref", + 'HaSize' : "haloSize", + 'SpTra' : "specTransp", + 'Alpha' : "alpha", + 'Spec' : "spec", + 'Emit' : "emit", + 'Hard' : "hard", + 'Amb' : "amb", + } + + _getters = {'rgbCol' : _getRGB, + 'specCol' : _getSpec, + 'mirCol' : _getMir, + } + + _setters = {'rgbCol' : _setRGB, + 'specCol' : _setSpec, + 'mirCol' : _setMir, + } + + t = _Material.Modes + + Modes = {'traceable' : t.TRACEABLE, + 'shadow' : t.SHADOW, + 'shadeless' : t.SHADELESS, + 'wire' : t.WIRE, + 'vcolLight' : t.VCOL_LIGHT, + 'vcolPaint' : t.VCOL_PAINT, + 'zTransp' : t.ZTRANSP, + 'zInvert' : t.ZINVERT, + 'onlyShadow': t.ONLYSHADOW, + 'star' : t.STAR, + 'texFace' : t.TEXFACE, + 'noMist' : t.NOMIST, + } + + t = _Material.HaloModes + + HaloModes = { "rings" : t.RINGS, + "lines" : t.LINES, + "tex" : t.TEX, + "haloPuno": t.PUNO, + "shade" : t.SHADE, + "flare" : t.FLARE, + } + + + del t + + def setMode(self, *args): + """Set the mode of 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes. + + Example:: + + m = Material.New() + m.setMode('shadow', 'wire') +""" + flags = 0 + try: + for a in args: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of" % self.Modes.keys() + self._object.mode = flags + + def setHaloMode(self, *args): + """Sets the material to Halo mode. +This function takes a variable number of string arguments of the types +listed in self.HaloModes""" + flags = _Material.Modes.HALO + + try: + for a in args: + flags |= self.HaloModes[a] + except: + raise TypeError, "mode must be one of" % self.HaloModes.keys() + self._object.mode = flags + + +class ModeFlags: + """Readonly dictionary + +...containing Material mode bitvectors: + +|------------------------------------------| +| Name | Description | +|==========================================| +| TRACEABLE | visible for shadow lamps | +|------------------------------------------| +| SHADOW | cast shadow | +|------------------------------------------| +| SHADELESS | do not shade | +|------------------------------------------| +| WIRE | draw in wireframe | +|------------------------------------------| +| VCOL_LIGHT | use vertex colors | +| | with lighting | +|------------------------------------------| +| VCOL_PAINT | vertex colours | +|------------------------------------------| +| HALO | Halo material | +|------------------------------------------| +| ZTRANSP | Z transparency | +|------------------------------------------| +| ZINVERT | invert Z | +|------------------------------------------| +| ONLYSHADOW | only shadow, but | +| | don't render | +|------------------------------------------| +| STAR | ? | +|------------------------------------------| +| TEXFACE | textured faces | +|------------------------------------------| +| NOMIST | disable mist | +|------------------------------------------| + +These mode flags directly represent the buttons in the Material parameters +window (EditButtons) + +Example:: + + # be 'm' a material + from Blender.Material.Modes import * + m.mode |= (TRACEABLE + WIRE) # Set 'wire' and 'traceable' flagsd + m.mode &= ~SHADELESS # clear 'shadeless' flag +""" + + t = _Material.Modes + TRACEABLE = t.TRACEABLE + SHADOW = t.SHADOW + SHADELESS = t.SHADELESS + WIRE = t.WIRE + VCOL_LIGHT = t.VCOL_LIGHT + VCOL_PAINT = t.VCOL_PAINT + HALO = t.HALO + ZTRANSP = t.ZTRANSP + ZINVERT = t.ZINVERT + ONLYSHADOW = t.ONLYSHADOW + STAR = t.STAR + TEXFACE = t.TEXFACE + NOMIST = t.NOMIST + del t + +# override: +ModeFlags = _Material.Modes + +def get(name = None): + """If 'name' given, the Material 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Materials is returned""" + if name: + return Material(_Material.get(name)) + else: + return shadow._List(_Material.get(), Material) + +Get = get # emulation + +def New(name = None): + """Creates a new, empty Material and returns it. + +Example:: + + from Blender import Material + mat = Material.New() +""" + mat = Material(_Material.New()) + if name: + mat.name = name + return mat diff --git a/intern/python/modules/Blender/Mesh.py b/intern/python/modules/Blender/Mesh.py new file mode 100644 index 00000000000..dd8103919f8 --- /dev/null +++ b/intern/python/modules/Blender/Mesh.py @@ -0,0 +1,250 @@ +"""The Blender Mesh module + + This module provides routines for more extensive mesh manipulation. + Later, this Mesh type will also allow interactive access (like in + EditMode). + In the Publisher, Ngons will also be supported (and converted to + triangles on mesh.update(). The following code demonstrates + creation of an Ngon. + + Example:: + + from Blender import Mesh, Object, Scene + + m = Mesh.New() # new empty mesh + vlist = [] + vlist.append(m.addVert((-0.0, -1.0, 0.0))) + vlist.append(m.addVert((1.0, 0.0, 0.0))) + vlist.append(m.addVert((1.0, 1.0, 0.0))) + vlist.append(m.addVert((0.0, 3.0, 0.0))) + vlist.append(m.addVert((-1.0, 2.0, 0.0))) + vlist.append(m.addVert((-3.0, 1.0, 0.0))) + vlist.append(m.addVert((-3.0, 3.0, 0.0))) + vlist.append(m.addVert((-4.0, 3.0, 0.0))) + vlist.append(m.addVert((-4.0, 0.0, 0.0))) + + f = m.addFace(vlist) + + # do some calculations: top project vertex coordinates to + # UV coordinates and normalize them to the square [0.0, 1.0]*[0.0, 1.0] + + uvlist = map(lambda x: (x.co[0], x.co[1]), vlist) + maxx = max(map(lambda x: x[0], uvlist)) + maxy = max(map(lambda x: x[1], uvlist)) + minx = min(map(lambda x: x[0], uvlist)) + miny = min(map(lambda x: x[1], uvlist)) + + len = max((maxx - minx), (maxy - miny)) + offx = -minx / len + offy = -miny / len + + f.uv = map(lambda x: (x[0]/len + offx, x[1]/len + offy), uvlist) # assign UV coordinates by 'top' projection + + m.update() # update and triangulate mesh + + ob = Object.New('Mesh') # create new Object + ob.link(m) # link mesh data + sc = Scene.getCurrent() # get current Scene + sc.link(ob) # link Object to scene +""" + +from Blender.Types import NMFaceType +import Blender.Material as Material + +from _Blender import NMesh as _NMesh + +FACEFLAGS = _NMesh.Const +DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC + +import shadow + +def makeFace(f): + face = _NMesh.Face() + for v in f: + face.v.append(v) + face.uv.append((v.uvco[0], v.uvco[1])) + return face + +def toTriangles(ngon): + from utils import tesselation + # This should be a Publisher only feature...once the tesselation + # is improved. The GLU tesselator of Mesa < 4.0 is crappy... + if len(ngon.uv) == len(ngon.v): + i = 0 + for v in ngon.v: + v.uvco = ngon.uv[i] + i += 1 + + return tesselation.NgonAsTriangles(ngon, makeFace) # return triangles + +def Color(r, g, b, a = 1.0): + return _NMesh.Col(255 * r, 255 * g, 255 * b, 255 * a) + +class Vert: #shadow NMVert class for the tesselator + """Vertex wrapper class +This class emulates a float coordinate vector triple +""" + def __init__(self): + self.vert = None + self.uv = [] + def __len__(self): + return 3 + def __setitem__(self, i, val): + self.vert[i] = val + def __getitem__(self, i): + return self.vert.co[i] + +class Face: + """Face wrapper class +This class emulates a list of vertex references +""" + def __init__(self, vlist): + self.v= vlist + self.uv = [] + + def __len__(self): + return len(self.v) + + def __setitem__(self, i, val): + self.v[i] = val + + def __getitem__(self, i): + return self.v[i] + +# override: + +Vert = _NMesh.Vert +Face = _NMesh.Face + +class rawMesh: + """Wrapper for raw Mesh data""" + def __init__(self, object = None): + if object: + self._object = object + else: + self._object = _NMesh.GetRaw() + + self.flags = DEFAULTFLAGS + self.smooth = 0 + self.recalc_normals = 1 + self.faces = self._object.faces[:] + + def __getattr__(self, name): + if name == 'vertices': + return self._object.verts + elif name == 'has_col': + return self._object.hasVertexColours() + elif name == 'has_uv': + return self._object.hasFaceUV() + else: + return getattr(self._object, name) + + def __repr__(self): + return "Mesh: %d faces, %d vertices" % (len(self.faces), len(self.verts)) + + def hasFaceUV(self, true = None): + """Sets the per-face UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasFaceUV() + return self._object.hasFaceUV(true) + + def hasVertexUV(self, true = None): + """Sets the per-vertex UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasVertexUV() + return self._object.hasVertexUV(true) + + def hasVertexColours(self, true = None): + """Sets the per-face UV texture flag, if 'true' specified (either + 0 or 1). Returns the texture flag in any case.""" + if true == None: + return self._object.hasVertexColours() + return self._object.hasVertexColours(true) + + def addVert(self, v): + """Adds a vertex to the mesh and returns a reference to it. 'v' can +be a float triple or any data type emulating a sequence, containing the +coordinates of the vertex. Note that the returned value references an +*owned* vertex""" + vert = _NMesh.Vert(v[0], v[1], v[2]) + self._object.verts.append(vert) + return vert + + def addFace(self, vlist, flags = None, makedefaultUV = 0): + """Adds a face to the mesh and returns a reference to it. 'vlist' +must be a list of vertex references returned by addVert(). +Note that the returned value references an *owned* face""" + if type(vlist) == NMFaceType: + face = vlist + else: + n = len(vlist) + face = _NMesh.Face(vlist) + if makedefaultUV: + face.uv = defaultUV[:n] + + self.faces.append(face) + # turn on default flags: + if not flags: + face.mode = self.flags + else: + face.mode = flags + return face + + def update(self): + """Updates the mesh datablock in Blender""" + o = self._object + o = self._object + o.faces = [] + smooth = self.smooth + for f in self.faces: + if len(f) > 4: #it's a NGON + faces = toTriangles(f) + for nf in faces: + nf.smooth = smooth + o.faces.append(nf) + else: + o.faces.append(f) + o.update() + + def link(self, material): + """Link material 'material' with the mesh. Note that a mesh can +currently have up to 16 materials, which are referenced by +Face().materialIndex""" + mats = self._object.materials + if material in mats: + print "material already assigned to mesh" + return + mats.append(material._object) + + def unlink(self, material): + """Unlink (remove) material 'material' from the mesh. Note +that the material indices per face need to be updated.""" + self._object.materials.remove(material._object) + + def setMaterials(self, materials = []): + """Sets materials. 'materials' must be a list of valid material objects +Note that a mesh can currently have up to 16 materials, which are referenced +by Face().materialIndex""" + + self._object.materials = (map(lambda x: x._object, materials)) + + def getMaterials(self, materials = []): + """Returns materials assigned to the mesh""" + return shadow._List(self._object.materials, Material.Material) + +def New(): + return rawMesh() + +def get(name = None): + """If 'name' given, the Mesh 'name' is returned if existing, 'None' otherwise.""" + if name: + ob = _NMesh.GetRaw(name) + if ob: + return rawMesh(ob) + else: + return None + else: + raise SystemError, "get() for Meshes is not yet supported" + diff --git a/intern/python/modules/Blender/NMesh.py b/intern/python/modules/Blender/NMesh.py new file mode 100644 index 00000000000..3e6c60bab21 --- /dev/null +++ b/intern/python/modules/Blender/NMesh.py @@ -0,0 +1,192 @@ +"""The Blender NMesh module + + This module provides access to the raw **Mesh** data block. + + Examples will not be given, as the life time of this module will be + most probably limited. Use the 'Mesh' module instead. +""" + +import _Blender.NMesh as _NMesh +import shadow + +class Mesh(shadow.shadow): + """The NMesh object + + This contains a copy of the raw mesh object data. + + Attributes + + verts -- A list of vertices of type 'Vert' + + faces -- List of faces of type 'Face' +""" + def update(self): + """updates the mesh object in Blender with the modified mesh data""" + self._object.update() + +class Vert: + """Vertex object + + Attributes + + co -- The vertex coordinates (x, y, z) + + no -- Vertex normal vector (nx, ny, nz) + + uvco -- Vertex texture ("sticky") coordinates + + index -- The vertex index, if owned by a mesh +""" + +class Face: + """Face object + + Attributes + + mode -- Display mode, see NMesh.FaceModes + + flag -- flag bit vector, specifying selection flags. + see NMesh.FaceFlags + + transp -- transparency mode bit vector; see NMesh.FaceTranspModes + + v -- List of Face vertices + + col -- List of Vertex colours + + materialIndex -- Material index (referring to one of the Materials in + the Meshes material list, see Mesh documentation + + smooth -- Flag whether smooth normals should be calculated (1 = yes) + + image -- Reference to texture image object + + uv -- A list of per-face UV coordinates: + [(u0, v0), (u1, v1), (u2, v2), .. ] +""" + +class Col: + """Colour object + + See NMesh module documentation for an example. + + Attributes + + r, g, b, a -- The RGBA components of the colour + A component must lie in the range of [0, 255] +""" + + +class FaceModes: + """Face mode bit flags + + BILLBOARD -- always orient after camera + + DYNAMIC -- respond to collisions + + INVISIBLE -- invisible face + + HALO -- halo face, always point to camera + + LIGHT -- dynamic lighting + + OBCOL -- use object colour instead of vertex colours + + SHADOW -- shadow type + + SHAREDCOL -- shared vertex colors (per vertex) + + TEX -- has texture image + + TILES -- uses tiled image + + TWOSIDE -- twosided face +""" + t = _NMesh.Const + BILLBOARD = t.BILLBOARD + DYNAMIC = t.DYNAMIC + INVISIBLE = t.INVISIBLE + HALO = t.HALO + LIGHT = t.LIGHT + OBCOL = t.OBCOL + SHADOW = t.SHADOW + SHAREDCOL = t.SHAREDCOL + TEX = t.TEX + TILES = t.TILES + TWOSIDE = t.TWOSIDE + del t + + +class FaceTranspModes: + """Readonly dictionary + +...containing Face transparency draw modes. They are of type 'enum', i.e. +can not be combined like a bit vector. + + SOLID -- draw solid + + ADD -- add to background(halo) + + ALPHA -- draw with transparency + + SUB -- subtract from background +""" + t = _NMesh.Const + SOLID = t.SOLID + ADD = t.ADD + ALPHA = t.ALPHA + SUB = t.SUB + del t + +class FaceFlags: + """Readonly dictionary + +...containing Face flags bitvectors: + + SELECT -- selected + + HIDE -- hidden + + ACTIVE -- the active face +""" + t = _NMesh.Const + SELECT = t.SELECT + HIDE = t.HIDE + ACTIVE = t.ACTIVE + del t + + +def New(name = None): + """Creates a new NMesh mesh object and returns it""" + pass + +def GetRaw(name = None): + """If 'name' specified, the Mesh object with 'name' is returned, 'None' +if not existant. Otherwise, a new empty Mesh is initialized and returned.""" + pass + +def PutRaw(mesh, name = "Mesh"): + """Creates a Mesh Object instance in Blender, i.e. a Mesh Object in the +current Scene and returns a reference to it. If 'name' specified, the Mesh +'name' is overwritten. In this case, no Object reference is returned.""" + pass + +def GetRawFromObject(name): + """This returns the mesh as used by the object, which +means it contains all deformations and modifications.""" + pass + +# override all these functions again, because we only used them for +# documentation -- NMesh will be no longer supported in future + +New = _NMesh.New +GetRaw = _NMesh.GetRaw +PutRaw = _NMesh.PutRaw +GetRawFromObject = _NMesh.GetRawFromObject +Const = _NMesh.Const +Vert = _NMesh.Vert +Face = _NMesh.Face +Col = _NMesh.Col + +def NMesh(data): + return data diff --git a/intern/python/modules/Blender/Object.py b/intern/python/modules/Blender/Object.py new file mode 100644 index 00000000000..7fefedf4725 --- /dev/null +++ b/intern/python/modules/Blender/Object.py @@ -0,0 +1,391 @@ +## +## Blender API mid level layer 01/2002 // strubi@blender.nl +## +## $Id$ +## + +"""The Blender Object module + + This module provides **Object** manipulation routines. + + Example:: + + from Blender import Object + ob = Object.get('Plane') + actobj = Object.getSelected()[0] # get active Object + print actobj.loc # print position + ob.makeParent([actobj]) # make ob the parent of actobj +""" + +import _Blender.Object as _Object + +import shadow +reload(shadow) # XXX + +class _C: + pass + +InstanceType = type(_C()) +del _C # don't export this + + +def _Empty_nodata(obj): + return None + +class Object(shadow.hasIPO): + """Blender Object + + A Blender Object (note the capital O) is the instance of a 3D structure, + or rather, the Object that is (normally) visible in your Blender Scene. + + An instance of a Blender Object object is created by:: + + from Blender import Object + ob = Object.New(type) # type must be a valid type string, + # see Object.Types + + ... + + Attributes + + Note that it is in general not recommended to access the Object's + attributes directly. Please rather use the get-/set- functions instead. + + loc -- position vector (LocX, LocY, LocZ) + + dloc -- delta position vector (dLocX, dLocY, dLocZ) + + rot -- euler rotation vector (RotX, RotY, RotZ). + Warning: this may change in future. + + drot -- delta rotation euler vector (dRotX, dRotY, dRotZ) + Warning: this may change in future. + + size -- scale vector (SizeX, SizeY, SizeZ) + + dsize -- delta scale vector (dSizeX, dSizeY, dSizeZ) + + layer -- layer bitvector (20 bit), defining what layers the object is + visible in + + + The following items are listed here only for compatibility to older + scripts and are READ-ONLY! **USE the get- functions instead!** + + data -- reference to the data object (e.g. Mesh, Camera, Lamp, etc.) + + parent -- reference to the parent object, if existing, 'None' otherwise. + + track -- reference to the tracked object, if existing, 'None' otherwise. + + This bit mask can be read and written: + + colbits -- the Material usage mask. A set bit #n means: + The Material #n in the *Object's* material list is used. + Otherwise, the Material #n of the Objects *Data* material list + is displayed. +""" + + def __init__(self, object = None): + """Returns an empty shadow Object""" + self._object = object + + def __repr__(self): + return "[Object \"%s\"]" % self.name + + def link(self, data): + """Links Object 'self' with data 'data'. The data type must match +the Object's type, so you cannot link a Lamp to a mesh type Object. +'data' can also be an Ipo object (IpoBlock) +""" + from _Blender import Types + # special case for NMesh: + if type(data) == Types.NMeshType: + return self._object.link(data) + elif type(data) == InstanceType: + if data.__class__.__name__ == "rawMesh": + data.update() # update mesh + elif data.__class__.__name__ == "IpoBlock": + self.setIpo(data) + + return shadow._link(self, data) + + def copy(self): + """Returns a copy of 'self'. +This is a true, linked copy, i.e. the copy shares the same data as the +original. The returned object is *free*, meaning, not linked to any scene.""" + return Object(self._object.copy()) + + #def clone(self): + #"""Makes a clone of the specified object in the current scene and +##returns its reference""" + #return Object(self._object.clone()) + + def shareFrom(self, object): + """Link data of 'self' with data of 'object'. This works only if +'object' has the same type as 'self'.""" + return Object(self._object.shareFrom(object._object)) + + def getMatrix(self): + """Returns the object matrix""" + return self._object.getMatrix() + + def getInverseMatrix(self): + """Returns the object's inverse matrix""" + return self._object.getInverseMatrix() + + def getData(self): + "Returns the Datablock object containing the object's data, e.g. Mesh" + t = self._object.getType() + data = self._object.data + try: + return self._dataWrappers[t][1](data) + except: + raise TypeError, "getData() not yet supported for this object type" + + def getDeformData(self): + """Returns the Datablock object containing the object's deformed data. +Currently, this is only supported for a Mesh""" + import _Blender.NMesh as _NMesh + t = self._object.getType() + if t == self.Types['Mesh']: + data = _NMesh.GetRawFromObject(self.name) + return self._dataWrappers[t][1](data) + else: + raise TypeError, "getDeformData() not yet supported for this object type" + + def getType(self): + "Returns type string of Object, which is one of Object.Types.keys()" + t = self._object.getType() + try: + return self._dataWrappers[t][0] + except: + return "<unsupported>" + + def getParent(self): + "Returns object's parent object" + if self._object.parent: + return Object(self._object.parent) + return None + + def getTracked(self): + "Returns object's tracked object" + if self._object.track: + return Object(self._object.track) + return None + +# FUTURE FEATURE :-) : +# def getLocation(): +# """Returns the object's location (x, y, z). +#By default, the location vector is always relative to the object's parent. +#If the location of another coordinate system is wanted, specify 'origin' by +#the object whose coordinate system the location should be calculated in. + +#If world coordinates are wanted, set 'relative' = "World".""" + + def getLocation(self, relative = None): + """Returns the object's location (x, y, z). For the moment, +'relative' has no effect.""" + l = self._object.loc + return (l[0], l[1], l[2]) + + def setLocation(self, location, relative = None): + """Sets the object's location. 'location' must be a vector triple. +See 'getLocation()' about relative coordinate systems.""" + l = self._object.loc # make sure this is copied + l[0], l[1], l[2] = location + + def getDeltaLocation(self): + """Returns the object's delta location (x, y, z)""" + l = self._object.dloc + return (l[0], l[1], l[2]) + + def setDeltaLocation(self, delta_location): + """Sets the object's delta location which must be a vector triple""" + l = self._object.dloc # make sure this is copied + l[0], l[1], l[2] = delta_location + + def getEuler(self): + """Returns the object's rotation as Euler rotation vector +(rotX, rotY, rotZ)""" + e = self._object.rot + return (e[0], e[1], e[2]) + + def setEuler(self, euler = (0.0, 0.0, 0.0)): + """Sets the object's rotation according to the specified Euler angles. +'euler' must be a vector triple""" + e = self._object.rot + e[0], e[1], e[2] = euler + + def makeParent(self, objlist, mode = 0, fast = 0): + """Makes 'self' the parent of the objects in 'objlist' which must be +a list of valid Objects. +If specified: + + mode -- 0: make parent with inverse + + 1: without inverse + + fast -- 0: update scene hierarchy automatically + + 1: don't update scene hierarchy (faster). In this case, you + must explicitely update the Scene hierarchy, see: + 'Blender.Scene.getCurrent().update()'""" + list = map(lambda x: x._object, objlist) + return Object(self._object.makeParent(list, mode, fast)) + + def clrParent(self, mode = 0, fast = 0): + """Clears parent object. +If specified: + + mode -- 2: keep object transform + + fast > 0 -- don't update scene hierarchy (faster)""" + return Object(self._object.clrParent(mode, fast)) + + def getMaterials(self): + """Returns list of materials assigned to the object""" + from Blender import Material + return shadow._List(self._object.getMaterials(), Material.Material) + + def setMaterials(self, materials = []): + """Sets materials. 'materials' must be a list of valid material objects""" + o = self._object + old_mask = o.colbits + o.colbits = -1 # set material->object linking + o.setMaterials(map(lambda x: x._object, materials)) + o.colbits = old_mask + + def materialUsage(self, flag): + """Determines the way the material is used and returns status. + +'flag' = 'Data' : Materials assigned to the object's data are shown. (default) + +'flag' = 'Object' : Materials assigned to the object are shown. + +The second case is desired when the object's data wants to be shared among +objects, but not the Materials assigned to their data. See also 'colbits' +attribute for more (and no future compatible) control.""" + if flag == "Object": + self._object.colbits = -1 + elif flag == "Data": + self._object.colbits = 0 + return self._object.colbits + else: + raise TypeError, "unknown mode %s" % flag + + _getters = {} + + from Blender import Mesh, Camera, Lamp + + t = _Object.Types + Types = {"Camera" : t.CAMERA, + "Empty" : t.EMPTY, + "Lamp" : t.LAMP, + "Mesh" : t.MESH, + } + + # create lookup table for data wrappers + _dataWrappers = range(max(Types.values()) + 1) + _dataWrappers[t.MESH] = ("Mesh", Mesh.rawMesh) + _dataWrappers[t.CAMERA] = ("Camera", Camera.Camera) + _dataWrappers[t.LAMP] = ("Lamp", Lamp.Lamp) + _dataWrappers[t.EMPTY] = ("Empty", _Empty_nodata) + + t = _Object.DrawTypes + DrawTypes = {"Bounds" : t.BOUNDBOX, + "Wire" : t.WIRE, + "Solid" : t.SOLID, + "Shaded" : t.SHADED, + } + + t = _Object.DrawModes + DrawModes = {"axis" : t.AXIS, + "boundbox" : t.BOUNDBOX, + "texspace" : t.TEXSPACE, + "name" : t.NAME, + } + + + del t + del Mesh, Camera, Lamp + + def getDrawMode(self): + """Returns the Object draw modes as a list of strings""" + return shadow._getModeBits(self.DrawModes, self._object.drawMode) + + def setDrawMode(self, *args): + """Sets the Object's drawing modes as a list of strings""" + self._object.drawMode = shadow._setModeBits(self.DrawModes, args) + + def getDrawType(self): + """Returns the Object draw type""" + for k in self.DrawTypes.keys(): + if self.DrawTypes[k] == self.drawType: + return k + + def setDrawType(self, name): + """Sets the Object draw type. 'name' must be one of: + +* 'Bounds' : Draw bounding box only + +* 'Wire' : Draw in wireframe mode + +* 'Solid' : Draw solid + +* 'Shaded' : Draw solid, shaded and textures +""" + try: + self._object.drawType = self.DrawTypes[name] + except: + raise TypeError, "type must be one of %s" % self.DrawTypes.keys() + + +################## +# MODULE FUNCTIONS + +def New(objtype, name = None): + """Creates a new, empty object and returns it. +'objtype' is a string and must be one of:: + + Camera + Empty + Mesh + Lamp + +More object types will be supported in future. + +Example:: + + ob = Object.New('Camera') +""" + + if type(objtype) == type(0): + obj = Object(_Object.New(objtype)) # emulate old syntax + else: + t = Object.Types[objtype] + obj = Object(_Object.New(t)) + return obj + +def get(name = None): + """If 'name' given, the Object 'name' is returned if existing, 'None' otherwise. +If no name is given, a list of all Objects is returned""" + if name: + ob = _Object.get(name) + if ob: + return Object(ob) + else: + return None + else: + return shadow._List(_Object.get(), Object) + +Get = get # emulation + +def getSelected(): + """Returns a list of selected Objects in the active layer(s). +The active object is the first in the list, if visible""" + return shadow._List(_Object.getSelected(), Object) + +GetSelected = getSelected # emulation + +Types = _Object.Types # for compatibility diff --git a/intern/python/modules/Blender/Scene.py b/intern/python/modules/Blender/Scene.py new file mode 100644 index 00000000000..a6deaeb5a46 --- /dev/null +++ b/intern/python/modules/Blender/Scene.py @@ -0,0 +1,143 @@ +"""The Blender Scene module + + This module provides *Scene* manipulation routines. + + Example:: + + from Blender import Scene + + curscene = Scene.getCurrent() + ob = curscene.getChildren()[0] # first object + newscene = Scene.New('testscene') + cam = curscene.getCurrentCamera() # get current camera object + newscene.link(ob) # link 'ob' to Scene + newscene.link(cam) + newscene.makeCurrent() # make current Scene +""" +import _Blender.Scene as _Scene + +from Object import Object +import shadow + +class Scene(shadow.shadowEx): + """Wrapper for Scene DataBlock +""" + def link(self, object): + """Links Object 'object' into Scene 'self'.""" + # This is a strange workaround; Python does not release + # 'self' (and thus self._object) when an exception in the C API occurs. + # Therefore, we catch that exception and do it ourselves.. + # Maybe Python 2.2 is able to resolve this reference dependency ? + try: + return self._object.link(object._object) + except: + del self._object + raise + + def unlink(self, object): + """Unlinks (deletes) Object 'object' from Scene.""" + ret = self._object.unlink(object._object) + return ret + + def copy(self, duplicate_objects = 1): + """Returns a copy of itself. + +The optional argument defines, how the Scene's children objects are +duplicated:: + + 0: Link Objects + 1: Link Object data + 2: Full Copy""" + return Scene(self._object.copy(duplicate_objects)) + + def update(self): + """Updates scene 'self'. + This function explicitely resorts the base list of a newly created object + hierarchy.""" + return self._object.update() + + def makeCurrent(self): + """Makes 'self' the current Scene""" + return self._object.makeCurrent() + + def frameSettings(self, start = None, end = None, current = None): + """Sets or retrieves the Scene's frame settings. +If the frame arguments are specified, they are set. +A tuple (start, end, current) is returned in any case.""" + if start and end and current: + return self._object.frameSettings(start, end, current) + else: + return self._object.frameSettings() + + def currentFrame(self, frame = None): + """If 'frame' is given, the current frame is set and returned in any case""" + if frame: + return self._object.frameSettings(-1, -1, frame) + return self._object.frameSettings()[2] + + def startFrame(self, frame = None): + """If 'frame' is given, the start frame is set and returned in any case""" + if frame: + return self._object.frameSettings(frame, -1, -1) + return self._object.frameSettings()[0] + + def endFrame(self, frame = None): + """If 'frame' is given, the end frame is set and returned in any case""" + if frame: + return self._object.frameSettings(-1, frame, -1) + return self._object.frameSettings()[1] + + def getChildren(self): + """Returns a list of the Scene's children Objects""" + return shadow._List(self._object.getChildren(), Object) + + def getCurrentCamera(self): + """Returns current active camera Object""" + cam = self._object.getCurrentCamera() + if cam: + return Object(cam) + + def setCurrentCamera(self, object): + """Sets the current active camera Object 'object'""" + return self._object.setCurrentCamera(object._object) + + def getRenderdir(self): + """Returns directory where rendered images are saved to""" + return self._object.getRenderdir(self._object) + + def getBackbufdir(self): + """Returns the Backbuffer images location""" + return self._object.getBackbufdir(self._object) + +# Module methods + +def New(name = 'Scene'): + """Creates and returns new Scene with (optionally given) name""" + return Scene(_Scene.New(name)) + +def get(name = None): + """Returns a Scene object with name 'name' if given, None if not existing, +or a list of all Scenes otherwise.""" + if name: + ob = _Scene.get(name) + if ob: + return Scene(ob) + else: + return None + else: + return shadow._List(_Scene.get(), Scene) + +Get = get # emulation + +def getCurrent(): + """Returns the currently active Scene""" + sc = Scene(_Scene.getCurrent()) + return sc + +def unlink(scene): + """Removes the Scene 'scene' from Blender""" + if scene._object.name == _Scene.getCurrent().name: + raise SystemError, "current Scene can not be removed!" + for ob in scene.getChildren(): + scene.unlink(ob) + return _Scene.unlink(scene._object) diff --git a/intern/python/modules/Blender/Text.py b/intern/python/modules/Blender/Text.py new file mode 100644 index 00000000000..0d5f615f190 --- /dev/null +++ b/intern/python/modules/Blender/Text.py @@ -0,0 +1,57 @@ +"""The Blender Text module + + This module lets you manipulate the Text buffers inside Blender. + Text objects are currently owned by the Text editor in Blender. + + Example:: + + from Blender import Text + text = Text.New('Text') # create new text buffer + text.write('hello') # write string + Text.unlink(text) # delete +""" + +import _Blender.Text as _Text + +class Text: + """Wrapper for Text DataBlock""" + + def clear(self): + """Clears the Text objects text buffer""" + pass + + def write(self, string): + """Appends 'string' to the text buffer""" + pass + + def asLines(self): + """Returns the text buffer as a list of lines (strings)""" + pass + + def set(self, attr, val): + """Set the Text attribute of name 'name' to value 'val'. + +Currently supported:: + + follow_cursor : 1: Text output follows the cursor""" + +# Module methods + +def New(name = None): + """Creates new empty Text with (optionally given) name and returns it""" + pass + +def get(name = None): + """Returns a Text object with name 'name' if given, 'None' if not existing, +or a list of all Text objects in Blender otherwise.""" + pass + +def unlink(text): + """Removes the Text 'text' from the Blender text window""" + pass + + +# override: +New = _Text.New +get = _Text.get +unlink = _Text.unlink diff --git a/intern/python/modules/Blender/Types.py b/intern/python/modules/Blender/Types.py new file mode 100644 index 00000000000..d49d9c35407 --- /dev/null +++ b/intern/python/modules/Blender/Types.py @@ -0,0 +1 @@ +from _Blender.Types import * diff --git a/intern/python/modules/Blender/Window.py b/intern/python/modules/Blender/Window.py new file mode 100644 index 00000000000..e51ab894dfa --- /dev/null +++ b/intern/python/modules/Blender/Window.py @@ -0,0 +1,65 @@ +"""The Blender Window module + +This module currently only supports redrawing commands of windows. +Later on, it will allow screen manipulations and access to Window +properties""" + +import _Blender.Window as _Window + +t = _Window.Types +Const = t # emulation + +Types = { 'View' : t.VIEW3D, + 'Ipo' : t.IPO, + 'Oops' : t.OOPS, + 'Button' : t.BUTS, + 'File' : t.FILE, + 'Image' : t.IMAGE, + 'Text' : t.TEXT, + 'Action' : t.ACTION, + } + +del t + +def Redraw(t= 'View'): + """Redraws all windows of the type 't' which must be one of: + +* "View" - The 3D view + +* "Ipo" - The Ipo Window + +* "Oops" - The OOPS (scenegraph) window + +* "Button" - The Button Window + +* "File" - The File Window + +* "Image" - The Image Window (UV editor) + +* "Text" - The Text editor + +* "Action" - The Action Window""" + + if type(t) == type(1): + return _Window.Redraw(t) + try: + _Window.Redraw(Types[t]) + except: + raise TypeError, "type must be one of %s" % Types.keys() + +def RedrawAll(): + """Redraws the whole screen""" + _Window.RedrawAll() + +def drawProgressBar(val, text): + """Draws a progress bar behind the Blender version information. +'val' is a float value <= 1.0, 'text' contains info about what is currently +being done. +This function must be called with 'val' = 0.0 at start and end of the executed +(and probably time consuming) action. +The user may cancel the progress with the 'Esc' key, in this case, 0 is returned, +1 else.""" + return _Window.draw_progressbar(val, text) + +draw_progressbar = _Window.draw_progressbar # emulation +QRedrawAll = _Window.QRedrawAll diff --git a/intern/python/modules/Blender/World.py b/intern/python/modules/Blender/World.py new file mode 100644 index 00000000000..e0c42d33f16 --- /dev/null +++ b/intern/python/modules/Blender/World.py @@ -0,0 +1,157 @@ +import _Blender.World as _World + +import shadow + +def _getAmbCol(obj): + return obj.ambR, obj.ambG, obj.ambB + +def _setAmbCol(obj, rgb): + obj.ambR, obj.ambG, obj.ambB = rgb + +def _getZenCol(obj): + return obj.zenR, obj.zenG, obj.zenB + +def _setZenCol(obj, rgb): + obj.zenR, obj.zenG, obj.zenB = rgb + +def _getHorCol(obj): + return obj.horR, obj.horG, obj.horB + +def _setHorCol(obj, rgb): + obj.horR, obj.horG, obj.horB = rgb + +def _setMist(obj, mist): + obj.mistStart = mist.start + obj.mistDepth = mist.depth + obj.mistHeight = mist.height + obj.mistType = mist.type + +def _getMist(obj): + mist = Mist() + mist.start = obj.mistStart + mist.depth = obj.mistDepth + mist.height = obj.mistHeight + mist.type = obj.mistType + return mist + +class World(shadow.hasIPO, shadow.hasModes): + """Wrapper for Blender World DataBlock + + Attributes + + horCol -- horizon colour triple '(r, g, b)' where r, g, b must lie + in the range of [0.0, 1.0] + + zenCol -- zenith colour triple + + ambCol -- ambient colour triple + + exposure -- exposure value + + mist -- mist structure, see class Mist + + starDensity -- star density (the higher, the more stars) + + starMinDist -- the minimum distance to the camera + + starSize -- size of the stars + + starColNoise -- star colour noise + + gravity -- The gravity constant (9.81 for earth gravity) +""" + + SkyTypes = {'blend' : 1, + 'real' : 2, + 'paper' : 4, + } + + Modes = {'mist' : 1, + 'stars' : 2, + } + + _emulation = {'Expos' : "exposure", + 'HorR' : "horR", + 'HorG' : "horG", + 'HorB' : "horB", + 'ZenR' : "zenR", + 'ZenG' : "zenG", + 'ZenB' : "zenB", + 'StarDi' : "starDensity", + 'StarSi' : "starSize", + 'MisSta' : "mistStart", + 'MisDi' : "mistDepth", + 'MisHi' : "mistHeight", + } + + _setters = {'horCol' : _getHorCol, + 'zenCol' : _getZenCol, + 'ambCol' : _getAmbCol, + 'mist' : _getMist, + } + + _setters = {'horCol' : _setHorCol, + 'zenCol' : _setZenCol, + 'ambCol' : _setAmbCol, + 'mist' : _setMist, + } + + def getSkyType(self): + """Returns a list of the set Sky properties, see setSkyType()""" + list = [] + for k in self.SkyTypes.keys(): + i = self.SkyTypes[k] + if self._object.skyType & i: + list.append(k) + return list + + def setSkyType(self, *args): + """Set the sky type. This function takes a variable number +of string arguments of ['blend', 'real', 'paper']""" + flags = 0 + try: + for a in args: + flags |= self.SkyTypes[a] + except: + raise TypeError, "mode must be one of" % self.SkyTypes.keys() + self._object.skyType = flags + + +class Mist: + """Mist structure + + Attributes + + start -- start of the mist + + depth -- depth of the "mist wall" + + height -- height of the mist layer +""" + + Types = { 'quadratic' : 0, + 'linear' : 1, + 'sqrt' : 2, + } + + def __init__(self): + self.start = 0.0 + self.depth = 0.0 + self.height = 0.0 + self.type = 0 + + def setType(self, name): + """Set the Mist type (one of ['quadratic', 'linear', 'sqrt'])""" + try: + t = self.Types[name] + else: + raise TypeError, "type must be one of %s" % self.Types.keys() + self.type = t + + def getType(self): + """Returns the Mist type as string. See setType()""" + for k in self.Types.keys(): + if self.Types[k] == self.type: + return k + + diff --git a/intern/python/modules/Blender/__init__.py b/intern/python/modules/Blender/__init__.py new file mode 100644 index 00000000000..7356d9ddf9f --- /dev/null +++ b/intern/python/modules/Blender/__init__.py @@ -0,0 +1,23 @@ +# +# The Blender main module wrapper +# (c) 06/2001, NaN // strubi@blender.nl + +__all__ = ["Object", "Image", "NMesh", "Window", "Mesh", "Tools", "sys", + "Lamp", "Scene", "Draw", "Camera", "Material", "Types", "Ipo", + "BGL"] + +import _Blender + +Get = _Blender.Get +Redraw = _Blender.Redraw +link = _Blender.link +bylink = _Blender.bylink + +import Object, Image, Mesh, Window, Tools, sys, Lamp, Scene, Draw, Camera +import Material, NMesh, BGL, Types, Ipo, Text + +deg = lambda x: 0.0174532925199 * x # conversion from degrees to radians + +import __builtin__ +__builtin__.deg = deg + diff --git a/intern/python/modules/Blender/shadow.py b/intern/python/modules/Blender/shadow.py new file mode 100644 index 00000000000..15c5de88f66 --- /dev/null +++ b/intern/python/modules/Blender/shadow.py @@ -0,0 +1,195 @@ +# +# Blender mid level modules +# author: strubi@blender.nl +# +# + +"""Shadow class module + + These classes shadow the internal Blender objects + + There is no need for you to use the shadow module really - it is + just there for documentation. Blender object classes with a common + subset of function members derive from these sub classes. +""" + + +def _List(list, Wrapper): + """This function returns list of wrappers, taking a list of raw objects +and the wrapper method""" + return map(Wrapper, list) + +def _getModeBits(dict, attr): + list = [] + for k in dict.keys(): + i = dict[k] + if attr & i: + list.append(k) + return list + +def _setModeBits(dict, args): + flags = 0 + try: + for a in args: + flags |= dict[a] + except: + raise TypeError, "mode must be one of %s" % dict.keys() + return flags + + +def _link(self, data): + """Links Object 'self' with data 'data'. The data type must match +the Object's type, so you cannot link a Lamp to a mesh type Object""" + try: + self._object.link(data._object) + except: + print "Users:", self._object.users + +class shadow: + """This is the shadow base class""" + _getters = {} + _setters = {} + _emulation = {} + + def __init__(self, object): + self._object = object + + def __getattr__(self, a): + try: + return getattr(self._object, a) + except: + if self._emulation.has_key(a): + return getattr(self._object, self._emulation[a]) + elif self._getters.has_key(a): + return self._getters[a](self) + else: + raise AttributeError, a + + def __setattr__(self, a, val): + if a == "_object": + self.__dict__['_object'] = val + return + + try: + setattr(self.__dict__['_object'], a, val) + except: + if self._emulation.has_key(a): + setattr(self.__dict__['_object'], self._emulation[a], val) + elif self._setters.has_key(a): + self._setters[a](self, val) + else: + raise AttributeError, a + link = _link + + def rename(self, name): + """Tries to set the name of the object to 'name'. If the name already +exists, a unique name is created by appending a version number (e.g. '.001') +to 'name'. The effective name is returned.""" + self._object.name = name + return self._object.name + +def _getattrEx(self, a): + if self._emulation.has_key(a): + return getattr(self._object, self._emulation[a]) + elif self._getters.has_key(a): + return self._getters[a](self) + else: + return getattr(self._object, a) + +class shadowEx: + """This is the shadow base class with a minor change; check for +emulation attributes happens before access to the raw object's attributes""" + _getters = {} + _setters = {} + _emulation = {} + + def __del__(self): + self.__dict__.clear() + + def __init__(self, object): + self._object = object + + def __getattr__(self, a): + return _getattrEx(self, a) + + def __setattr__(self, a, val): + if a == "_object": + self.__dict__['_object'] = val + return + + if self._emulation.has_key(a): + setattr(self.__dict__['_object'], self._emulation[a], val) + elif self._setters.has_key(a): + self._setters[a](self, val) + else: + setattr(self.__dict__['_object'], a, val) + + def __repr__(self): + return repr(self._object) + + def rename(self, name): + """Tries to set the name of the object to 'name'. If the name already +exists, a unique name is created by appending a version number (e.g. '.001') +to 'name'. The effective name is returned.""" + self._object.name = name + return self._object.name + + link = _link + +class hasIPO(shadowEx): + """Object class which has Ipo curves assigned""" + + def getIpo(self): + "Returns the Ipo assigned to 'self'" + import Ipo + return Ipo.IpoBlock(self._object.ipo) + + def setIpo(self, ipo): + "Assigns the IpoBlock 'ipo' to 'self'" + return self._object.assignIpo(ipo._object) + + def __getattr__(self, a): + if a == "ipo": + print "ipo member access deprecated, use self.getIpo() instead!" + return self.getIpo() + else: + return _getattrEx(self, a) + +class hasModes(shadowEx): + """Object class which has different Modes""" + def getMode(self): + """Returns a list of the modes which are set for 'self'""" + list = [] + for k in self.Modes.keys(): + i = self.Modes[k] + if self._object.mode & i: + list.append(k) + return list + + def setMode(self, *args): + """Set the mode of 'self'. This function takes a variable number +of string arguments of the types listed in self.Modes""" + flags = 0 + try: + for a in args: + flags |= self.Modes[a] + except: + raise TypeError, "mode must be one of" % self.Modes.keys() + self._object.mode = flags + +class dict: + """readonly dictionary shadow""" + _emulation = {} + + def __init__(self, dict): + self._dict = dict + + def __getitem__(self, key): + try: + return self._dict[key] + except: + key = _emulation[key] + return self._dict[key] + + def __repr__(self): + return repr(self._dict) diff --git a/intern/python/modules/Blender/sys.py b/intern/python/modules/Blender/sys.py new file mode 100644 index 00000000000..f76c0074c1f --- /dev/null +++ b/intern/python/modules/Blender/sys.py @@ -0,0 +1,20 @@ +from _Blender.sys import * + +sep = dirsep # path separator ('/' or '\') + +class Path: + def dirname(self, name): + return dirname(name) + def join(self, a, *p): + path = a + for b in p: + if b[:1] == dirsep: + path = b + elif path == '' or path[-1:] == dirsep: + path = path + b + else: + path = path + dirsep + b + return path + +path = Path() + |