BPython:
[blender.git] / source / blender / python / api2_2x / Library.c
1 /**
2  * $Id$
3  *
4  * Blender.Library BPython module implementation.
5  * This submodule has functions to append data from .blend files.
6  * 
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * This is a new part of Blender.
30  *
31  * Contributor(s): Willian P. Germano
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34 */
35
36 #include <Python.h>
37 #include <stdio.h>
38
39 #include <DNA_ID.h>
40 #include <BKE_library.h> /* for all_local */
41 #include "BKE_displist.h" /* for set_displist_onlyzero */
42 #include "BKE_font.h" /* for text_to_curve */
43 #include <BLO_readfile.h>
44 #include <BLI_linklist.h>
45 #include <MEM_guardedalloc.h>
46
47 #include "gen_utils.h"
48 #include "modules.h"
49
50 /**
51  * Global variables.
52  */
53 static BlendHandle *bpy_openlib; /* ptr to the open .blend file */
54 static char *bpy_openlibname; /* its pathname */
55
56 /**
57  * Function prototypes for the Library submodule.
58  */
59 static PyObject *M_Library_Open(PyObject *self, PyObject *args);
60 static PyObject *M_Library_Close(PyObject *self);
61 static PyObject *M_Library_GetName(PyObject *self);
62 static PyObject *M_Library_Update(PyObject *self);
63 static PyObject *M_Library_Datablocks(PyObject *self, PyObject *args);
64 static PyObject *M_Library_Load(PyObject *self, PyObject *args);
65 static PyObject *M_Library_LinkableGroups(PyObject *self);
66
67 /**
68  * Module doc strings.
69  */     
70 static char M_Library_doc[]=
71 "The Blender.Library submodule:\n\n\
72 This module gives access to .blend files, using them as libraries of\n\
73 data that can be loaded into the current scene in Blender.";
74
75 static char Library_Open_doc[] =
76 "(filename) - Open the given .blend file for access to its objects.\n\
77 If another library file is still open, it's closed automatically.";
78
79 static char Library_Close_doc[] =
80 "() - Close the currently open library file, if any.";
81
82 static char Library_GetName_doc[] =
83 "() - Get the filename of the currently open library file, if any.";
84
85 static char Library_Datablocks_doc[] =
86 "(datablock) - List all datablocks of the given type in the currently\n\
87 open library file.\n\
88 (datablock) - datablock name as a string: Object, Mesh, etc.";
89
90 static char Library_Load_doc[] =
91 "(name, datablock [,update = 1]) - Append object 'name' of type 'datablock'\n\
92 from the open library file to the current scene.\n\
93 (name) - (str) the name of the object.\n\
94 (datablock) - (str) the datablock of the object.\n\
95 (update = 1) - (int) if non-zero, all display lists are recalculated and the\n\
96 links are updated.  This is slow, set it to zero if you have more than one\n\
97 object to load, then call Library.Update() after loading them all.";
98
99 static char Library_Update_doc[] =
100 "() - Update the current scene, linking all loaded library objects and\n\
101 remaking all display lists.  This is slow, call it only once after loading\n\
102 all objects (load each of them with update = 0:\n\
103 Library.Load(name, datablock, 0), or the update will be automatic, repeated\n\
104 for each loaded object.";
105
106 static char Library_LinkableGroups_doc[] =
107 "() - Get all linkable groups from the open .blend library file.";
108
109 /**
110  * Python method structure definition for Blender.Library submodule.
111  */
112 struct PyMethodDef M_Library_methods[] = {
113         {"Open", M_Library_Open, METH_VARARGS, Library_Open_doc},
114         {"Close",(PyCFunction)M_Library_Close, METH_NOARGS, Library_Close_doc},
115         {"GetName",(PyCFunction)M_Library_GetName, METH_NOARGS, Library_GetName_doc},
116         {"Update",(PyCFunction)M_Library_Update, METH_NOARGS, Library_Update_doc},
117         {"Datablocks", M_Library_Datablocks, METH_VARARGS, Library_Datablocks_doc},
118         {"Load", M_Library_Load, METH_VARARGS, Library_Load_doc},
119         {"LinkableGroups",(PyCFunction)M_Library_LinkableGroups,
120                 METH_NOARGS, Library_LinkableGroups_doc},
121         {NULL, NULL, 0, NULL}
122 };
123
124 /* Submodule Python functions: */
125
126 /**
127  * Open a new .blend file.
128  * Only one can be open at a time, so this function also closes
129  * the previously opened file, if any.
130  */
131 PyObject *M_Library_Open(PyObject *self, PyObject *args)
132 {
133         char *fname = NULL;
134         int len = 0;
135
136         if (!PyArg_ParseTuple (args, "s", &fname)) {
137                 return EXPP_ReturnPyObjError (PyExc_TypeError,
138                         "expected a .blend filename");
139         }
140
141         if (bpy_openlib) {
142                 M_Library_Close(self);
143                 Py_DECREF(Py_None); /* incref'ed by above function */
144         }
145
146         bpy_openlib = BLO_blendhandle_from_file(fname);
147
148         if (!bpy_openlib) return Py_BuildValue("i", 0);
149
150         len = strlen(fname) + 1; /* +1 for terminating '\0' */
151
152         bpy_openlibname = MEM_mallocN(len, "bpy_openlibname");
153
154         if (bpy_openlibname)
155                 PyOS_snprintf (bpy_openlibname, len, "%s", fname);
156
157         return Py_BuildValue("i", 1);
158 }
159
160 /**
161  * Close the current .blend file, if any.
162  */
163 PyObject *M_Library_Close(PyObject *self)
164 {
165         if (bpy_openlib) {
166                 BLO_blendhandle_close(bpy_openlib);
167                 bpy_openlib = NULL;
168         }
169
170         if (bpy_openlibname) {
171                 MEM_freeN (bpy_openlibname);
172                 bpy_openlibname = NULL;
173         }
174
175         Py_INCREF(Py_None);
176         return Py_None;
177 }
178
179 /**
180  * helper function for 'atexit' clean-ups, used by BPY_end_python,
181  * declared in EXPP_interface.h.
182  */
183 void EXPP_Library_Close(void)
184 {
185         if (bpy_openlib) {
186                 BLO_blendhandle_close(bpy_openlib);
187                 bpy_openlib = NULL;
188         }
189
190         if (bpy_openlibname) {
191                 MEM_freeN (bpy_openlibname);
192                 bpy_openlibname = NULL;
193         }
194 }
195
196 /**
197  * Get the filename of the currently open library file, if any.
198  */
199 PyObject *M_Library_GetName(PyObject *self)
200 {
201         if (bpy_openlib && bpy_openlibname)
202                 return Py_BuildValue("s", bpy_openlibname);
203
204         Py_INCREF (Py_None);
205         return Py_None;
206 }
207
208 /**
209  * Return a list with all items of a given datablock type
210  * (like 'Object', 'Mesh', etc.) in the open library file.
211  */
212 PyObject *M_Library_Datablocks(PyObject *self, PyObject *args)
213 {
214         char *name = NULL;
215         int blocktype = 0;
216         LinkNode *l = NULL, *names = NULL;
217         PyObject *list = NULL;
218
219         if (!bpy_openlib) {
220                 return EXPP_ReturnPyObjError(PyExc_IOError,
221                         "no library file: open one first with Blender.Lib_Open(filename)");
222         }
223
224         if (!PyArg_ParseTuple (args, "s", &name)) {
225                 return EXPP_ReturnPyObjError (PyExc_TypeError,
226                         "expected a string (datablock type) as argument.");
227         }
228
229         blocktype = (int)BLO_idcode_from_name(name);
230
231         if (!blocktype) {
232                 return EXPP_ReturnPyObjError (PyExc_NameError,
233                         "no such Blender datablock type");
234         }
235
236         names = BLO_blendhandle_get_datablock_names(bpy_openlib, blocktype);
237
238         if (names) {
239                 int counter = 0;
240                 list = PyList_New(BLI_linklist_length(names));
241                 for (l = names; l; l = l->next) {
242                         PyList_SET_ITEM(list, counter, Py_BuildValue("s", (char *)l->link));
243                         counter++;
244                 }
245                 BLI_linklist_free(names, free); /* free linklist *and* each node's data */
246                 return list;
247         }
248
249         Py_INCREF (Py_None);
250         return Py_None;
251 }
252
253 /**
254  * Return a list with the names of all linkable groups in the
255  * open library file.
256  */
257 PyObject *M_Library_LinkableGroups(PyObject *self)
258 {
259         LinkNode *l = NULL, *names = NULL;
260         PyObject *list = NULL;
261
262         if (!bpy_openlib) {
263                 return EXPP_ReturnPyObjError(PyExc_IOError,
264                         "no library file: open one first with Blender.Lib_Open(filename)");
265         }
266
267         names = BLO_blendhandle_get_linkable_groups(bpy_openlib);
268
269         if (names) {
270                 int counter = 0;
271                 list = PyList_New(BLI_linklist_length(names));
272                 for (l = names; l; l = l->next) {
273                         PyList_SET_ITEM(list, counter, Py_BuildValue("s", (char *)l->link));
274                         counter++;
275                 }
276                 BLI_linklist_free(names, free); /* free linklist *and* each node's data */
277                 return list;
278         }
279
280         Py_INCREF (Py_None);
281         return Py_None;
282 }
283
284 /**
285  * Load (append) a given datablock of a given datablock type
286  * to the current scene.
287  */
288 PyObject *M_Library_Load(PyObject *self, PyObject *args)
289 {
290         char *name = NULL;
291         char *base = NULL;
292         int update = 1;
293         int blocktype = 0;
294
295         if (!bpy_openlib) {
296                 return EXPP_ReturnPyObjError(PyExc_IOError,
297                         "no library file: you need to open one, first.");
298         }
299
300         if (!PyArg_ParseTuple (args, "ss|i", &name, &base, &update)) {
301                 return EXPP_ReturnPyObjError (PyExc_TypeError,
302                         "expected two strings as arguments.");
303         }
304
305         blocktype = (int)BLO_idcode_from_name(base);
306
307         if (!blocktype) {
308                 return EXPP_ReturnPyObjError (PyExc_NameError,
309                         "no such Blender datablock type");
310         }
311
312         BLO_script_library_append(bpy_openlib, bpy_openlibname, name, blocktype);
313
314         if (update) {
315                 M_Library_Update(self);
316                 Py_DECREF(Py_None); /* incref'ed by above function */
317         }
318
319         Py_INCREF (Py_None);
320         return Py_None;
321 }
322
323 /**
324  * Update all links and remake displists.
325  */
326 PyObject *M_Library_Update(PyObject *self)
327 { /* code adapted from do_library_append in src/filesel.c: */ 
328         Object *ob = NULL;
329         Library *lib = NULL;
330
331         ob = G.main->object.first;
332         set_displist_onlyzero(1);
333         while (ob) {
334                 if (ob->id.lib) {
335                         if (ob->type==OB_FONT) {
336                                 Curve *cu= ob->data;
337                                 if (cu->nurb.first==0) text_to_curve(ob, 0);
338                         }
339                         makeDispList(ob);
340                 }
341                 else {
342                         if (ob->type == OB_MESH && ob->parent && ob->parent->type == OB_LATTICE)
343                                 makeDispList(ob);
344                 }
345
346                 ob = ob->id.next;
347         }
348         set_displist_onlyzero(0);
349
350         if (bpy_openlibname) {
351                 strcpy(G.lib, bpy_openlibname);
352
353                 /* and now find the latest append lib file */
354                 lib = G.main->library.first;
355                 while (lib) {
356                         if (strcmp(bpy_openlibname, lib->name) == 0) break;
357                         lib = lib->id.next;
358                 }
359                 all_local(lib);
360         }
361
362         Py_INCREF (Py_None);
363         return Py_None;
364 }
365
366 /**
367  * Initialize the Blender.Library submodule.
368  * Called by Blender_Init in Blender.c .
369  * @return the registered submodule.
370  */
371 PyObject *Library_Init (void)
372 {
373         PyObject *submod;
374
375         submod = Py_InitModule3("Blender.Library", M_Library_methods, M_Library_doc);
376
377         return submod;
378 }