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