Initial revision
[blender.git] / intern / python / Blender.py
1 #! /usr/bin/env python
2
3 #######################
4 # (c) Jan Walter 2000 #
5 #######################
6
7 # CVS
8 # $Author$
9 # $Date$
10 # $RCSfile$
11 # $Revision$
12
13 """This is the Python API for Blender"""
14
15 def _findNewName(name, names):
16     import string
17     words = string.split(name, ".")
18     basename = words[0]
19     newname  = name
20     num = 1
21     while newname in names:
22         newname = basename + ".%03d" % num
23         num = num + 1
24     return newname
25
26 ###################
27 # Blender classes #
28 ###################
29
30 class Camera:
31     def __init__(self, name, Lens = 35.0, ClipSta = 0.1, ClipEnd = 100.0):
32         self.name = name
33         self.ipos = {}
34         self.Lens = Lens
35         self.ClipSta = ClipSta
36         self.ClipEnd = ClipEnd
37
38 class Curve:
39     def __init__(self, name):
40         # ...
41         self.name = name
42         self.ipos = {}
43         self.materials = []
44
45 class Ika:
46     def __init__(self, name):
47         self.name = name
48
49 class Ipo:
50     def __init__(self, name):
51         self.name = name
52
53 class Lamp:
54     def __init__(self, name, Energ = 1.0, R = 1.0, G = 1.0, B = 1.0,
55                  SpoSi = 45.0,
56                  OfsX = 0.0, OfsY = 0.0, OfsZ = 0.0,
57                  SizeX = 1.0, SizeY = 1.0, SizeZ = 1.0):
58         self.name = name
59         self.ipos = {}
60         self.Energ = Energ
61         self.R = R
62         self.G = G
63         self.B = B
64         self.SpoSi = SpoSi
65         self.OfsX = OfsX
66         self.OfsY = OfsY
67         self.OfsZ = OfsZ
68         self.SizeX = SizeX
69         self.SizeY = SizeY
70         self.SizeZ = SizeZ
71
72 class Material:
73     def __init__(self, name,
74                  R = 0.8, G = 0.8, B = 0.8,
75                  SpecR = 1.0, SpecG = 1.0, SpecB = 1.0,
76                  MirR = 1.0, MirG = 1.0, MirB = 1.0,
77                  Ref = 0.8, Alpha = 1.0, Emit = 0.0, Amb = 0.5,
78                  Spec = 0.5, Hard = 50):
79         self.name = name
80         self.ipos = {}
81         self.R = R
82         self.G = G
83         self.B = B
84         self.SpecR = SpecR
85         self.SpecG = SpecG
86         self.SpecB = SpecB
87         self.MirR = MirR
88         self.MirG = MirG
89         self.MirB = MirB
90         self.Ref = Ref
91         self.Alpha = Alpha
92         self.Emit = Emit
93         self.Amb = Amb
94         self.Spec = Spec
95         self.Hard = Hard
96
97 class Matrix:
98     def __init__(self):
99         self.elements = [[1, 0, 0, 0],
100                          [0, 1, 0, 0],
101                          [0, 0, 1, 0],
102                          [0, 0, 0, 1]]
103
104     def __repr__(self):
105         str = "%s" % self.elements
106         return str
107
108 class Mesh:
109     """Creates an (empty) instance of a Blender mesh.\n\
110     E.g.: "m = Blender.Mesh('Plane')"\n\
111     To create faces first add vertices with \n\
112     "i1 = m.addVertex(x, y, z, nx, ny, nz, r = -1.0, r = 0.0, b = 0.0)"\n\
113     then create faces with "index = m.addFace(i1, i2, i3, i4, isSmooth)"."""
114
115     _meshes = {}
116
117     def __init__(self, name):
118         self.name = name
119         self.ipos = {}
120         self.materials = []
121         self.vertices = []
122         self.normals = []
123         self.colors = []
124         self.faces = []
125         if name in Mesh._meshes.keys():
126             print 'Mesh "%s" already exists ...' % name
127             self.name = _findNewName(name, Mesh._meshes.keys())
128             print '... so it will be called "%s"' % self.name
129         Mesh._meshes[self.name] = self
130
131     def __repr__(self):
132         str = 'Mesh(name = "%s",\n' % self.name
133         str = str + '     vertices = %s,\n' % len(self.vertices)
134         str = str + '     faces = %s)' % len(self.faces)
135         return str
136
137     def addFace(self, i1, i2, i3, i4, isSmooth):
138         """addFace(self, i1, i2, i3, i4)"""
139         self.faces.append([i1, i2, i3, i4, isSmooth])
140         return (len(self.faces) - 1)
141
142     def addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0):
143         """addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0)"""
144         self.vertices.append([x, y, z])
145         self.normals.append([nx, ny, nz])
146         if r != -1.0:
147             self.colors.append([r, g, b])
148         return (len(self.vertices) - 1)
149
150 class MetaBall:
151     def __init__(self, name):
152         self.name = name
153
154 class Object:
155     """Creates an instance of a Blender object"""
156
157     _objects = {}
158
159     def __init__(self, name):
160         self.name = name
161         self.ipos = {}
162         self.materials = []
163         self.matrix = Matrix()
164         self.data = None
165         self.type = None
166         if name in Object._objects.keys():
167             print 'Object "%s" already exists ...' % name
168             self.name = _findNewName(name, Object._objects.keys())
169             print '... so it will be called "%s"' % self.name
170         Object._objects[self.name] = self
171
172     def __repr__(self):
173         str = 'Object(name = "%s",\n' % self.name
174         str = str + '       matrix = %s,\n' % self.matrix
175         if self.type:
176             str = str + '       data = %s("%s"))' % (self.type, self.data)
177         else:
178             str = str + '       data = None)'
179         return str
180
181 class Scene:
182     """Creates an instance of a Blender scene"""
183
184     _scenes = {}
185
186     def __init__(self, name):
187         self.name = name
188         self.objects = []
189 ##         self.camera = None
190 ##         self.world = None
191         Scene._scenes[self.name] = self
192
193     def __repr__(self):
194         str = 'Scene(name = "%s", \n' % self.name
195         str = str + '      objects = %s)' % len(self.objects)
196         return str
197
198     def addObject(self, object):
199         """addObject(self, object)"""
200         self.objects.append(object.name)
201         return (len(self.objects) - 1)
202
203 class Surface:
204     def __init__(self, name):
205         self.name = name
206         self.ipos = {}
207         self.materials = []
208         # ...
209
210 class Text(Surface):
211     def __init__(self, name):
212         Surface.__init__(name)
213
214 ##############
215 # primitives #
216 ##############
217
218 def addMesh(type, sceneName):
219     """Blender.addMesh(type, sceneName)\n\
220     where type is one of ["Plane"]"""
221
222     if type == "Plane":
223         object = Object(type)
224         mesh = Mesh(type)
225         i1 = mesh.addVertex(+1.0, +1.0, 0.0, 0.0, 0.0, 1.0)
226         i2 = mesh.addVertex(+1.0, -1.0, 0.0, 0.0, 0.0, 1.0)
227         i3 = mesh.addVertex(-1.0, -1.0, 0.0, 0.0, 0.0, 1.0)
228         i4 = mesh.addVertex(-1.0, +1.0, 0.0, 0.0, 0.0, 1.0)
229         mesh.addFace(i1, i4, i3, i2, 0)
230         connect("OB" + object.name, "ME" + mesh.name)
231         connect("SC" + sceneName,  "OB" + object.name)
232         return object.name, mesh.name
233     elif type == "Cube":
234         pass
235     elif type == "Circle":
236         pass
237     elif type == "UVsphere":
238         pass
239     elif type == "Icosphere":
240         pass
241     elif type == "Cylinder":
242         pass
243     elif type == "Tube":
244         pass
245     elif type == "Cone":
246         pass
247     elif type == "Grid":
248         pass
249     else:
250         raise TypeError
251
252 def addCurve(type):
253     if type == "Bezier Curve":
254         pass
255     elif type == "Bezier Circle":
256         pass
257     elif type == "Nurbs Curve":
258         pass
259     elif type == "Nurbs Circle":
260         pass
261     elif type == "Path":
262         pass
263     else:
264         raise TypeError
265
266 def addSurface(type):
267     if type == "Curve":
268         pass
269     elif type == "Circle":
270         pass
271     elif type == "Surface":
272         pass
273     elif type == "Tube":
274         pass
275     elif type == "Sphere":
276         pass
277     elif type == "Donut":
278         pass
279     else:
280         raise TypeError
281
282 def connect(objName1, objName2):
283     """connect(objName1, objName2)"""
284
285     if objName1[:2] == "OB" and objName2[:2] == "ME":
286         obj1 = getObject(objName1[2:])
287         obj1.data = objName2[2:]
288         obj1.type = "Mesh"
289     elif objName1[:2] == "SC" and objName2[:2] == "OB":
290         obj1 = getScene(objName1[2:])
291         obj2 = getObject(objName2[2:])
292         obj1.addObject(obj2)
293     else:
294         print "ERROR: connect(%s, %s)" % (objName1, objName2)
295
296 def getCurrentScene():
297     """getCurrentScene()"""
298
299     return Scene._scenes[0]
300
301 def getMesh(name):
302     """getMesh(name)"""
303
304     if name in Mesh._meshes.keys():
305         return Mesh._meshes[name]
306     else:
307         return None
308
309 def getObject(name):
310     """getObject(name)"""
311
312     if name in Object._objects.keys():
313         return Object._objects[name]
314     else:
315         return None
316
317 def getScene(name):
318     """getScene(name)"""
319
320     if name in Scene._scenes.keys():
321         return Scene._scenes[name]
322     else:
323         return None
324
325 def testBlender():
326     scene = Scene("1")
327     print scene
328     objName, meshName = addMesh("Plane", "1")
329     print scene
330     obj = Object("Plane")
331     connect("OB" + obj.name, "ME" + meshName)
332     connect("SC" + scene.name, "OB" + obj.name)
333     print scene
334     for name in scene.objects:
335         obj = getObject(name)
336         print obj
337         if obj.type == "Mesh":
338             mesh = getMesh(obj.data)
339             print mesh
340             print mesh.vertices
341             print mesh.faces
342     Mesh("Plane")
343     # print global data
344     print Scene._scenes
345     print Object._objects
346     print Mesh._meshes
347
348 if __name__ == "__main__":
349     testBlender()