Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Campbell Barton 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00034 /* nifty feature. swap out strings for RNA data */ 00035 #define USE_RNA_DATABLOCKS 00036 00037 #include <Python.h> 00038 #include <stddef.h> 00039 00040 #include "BLO_readfile.h" 00041 00042 #include "BKE_global.h" 00043 #include "BKE_main.h" 00044 #include "BKE_library.h" 00045 #include "BKE_idcode.h" 00046 #include "BKE_report.h" 00047 #include "BKE_context.h" 00048 00049 #include "BLI_utildefines.h" 00050 #include "BLI_string.h" 00051 #include "BLI_linklist.h" 00052 #include "BLI_path_util.h" 00053 #include "BLI_listbase.h" 00054 00055 #include "DNA_space_types.h" /* FILE_LINK, FILE_RELPATH */ 00056 00057 #include "bpy_util.h" 00058 00059 #ifdef USE_RNA_DATABLOCKS 00060 # include "bpy_rna.h" 00061 # include "RNA_access.h" 00062 #endif 00063 00064 typedef struct { 00065 PyObject_HEAD /* required python macro */ 00066 /* collection iterator specific parts */ 00067 char relpath[FILE_MAX]; 00068 char abspath[FILE_MAX]; /* absolute path */ 00069 BlendHandle *blo_handle; 00070 int flag; 00071 PyObject *dict; 00072 } BPy_Library; 00073 00074 static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds); 00075 static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *args); 00076 static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args); 00077 static PyObject *bpy_lib_dir(BPy_Library *self); 00078 00079 static PyMethodDef bpy_lib_methods[] = { 00080 {"__enter__", (PyCFunction)bpy_lib_enter, METH_NOARGS}, 00081 {"__exit__", (PyCFunction)bpy_lib_exit, METH_VARARGS}, 00082 {"__dir__", (PyCFunction)bpy_lib_dir, METH_NOARGS}, 00083 {NULL} /* sentinel */ 00084 }; 00085 00086 static void bpy_lib_dealloc(BPy_Library *self) 00087 { 00088 Py_XDECREF(self->dict); 00089 Py_TYPE(self)->tp_free(self); 00090 } 00091 00092 00093 static PyTypeObject bpy_lib_Type = { 00094 PyVarObject_HEAD_INIT(NULL, 0) 00095 "bpy_lib", /* tp_name */ 00096 sizeof(BPy_Library), /* tp_basicsize */ 00097 0, /* tp_itemsize */ 00098 /* methods */ 00099 (destructor)bpy_lib_dealloc,/* tp_dealloc */ 00100 NULL, /* printfunc tp_print; */ 00101 NULL, /* getattrfunc tp_getattr; */ 00102 NULL, /* setattrfunc tp_setattr; */ 00103 NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ 00104 NULL, /* tp_repr */ 00105 00106 /* Method suites for standard classes */ 00107 00108 NULL, /* PyNumberMethods *tp_as_number; */ 00109 NULL, /* PySequenceMethods *tp_as_sequence; */ 00110 NULL, /* PyMappingMethods *tp_as_mapping; */ 00111 00112 /* More standard operations (here for binary compatibility) */ 00113 00114 NULL, /* hashfunc tp_hash; */ 00115 NULL, /* ternaryfunc tp_call; */ 00116 NULL, /* reprfunc tp_str; */ 00117 00118 /* will only use these if this is a subtype of a py class */ 00119 NULL /*PyObject_GenericGetAttr is assigned later */, /* getattrofunc tp_getattro; */ 00120 NULL, /* setattrofunc tp_setattro; */ 00121 00122 /* Functions to access object as input/output buffer */ 00123 NULL, /* PyBufferProcs *tp_as_buffer; */ 00124 00125 /*** Flags to define presence of optional/expanded features ***/ 00126 Py_TPFLAGS_DEFAULT, /* long tp_flags; */ 00127 00128 NULL, /* char *tp_doc; Documentation string */ 00129 /*** Assigned meaning in release 2.0 ***/ 00130 /* call function for all accessible objects */ 00131 NULL, /* traverseproc tp_traverse; */ 00132 00133 /* delete references to contained objects */ 00134 NULL, /* inquiry tp_clear; */ 00135 00136 /*** Assigned meaning in release 2.1 ***/ 00137 /*** rich comparisons ***/ 00138 NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ 00139 00140 /*** weak reference enabler ***/ 00141 0, 00142 /*** Added in release 2.2 ***/ 00143 /* Iterators */ 00144 NULL, /* getiterfunc tp_iter; */ 00145 NULL, /* iternextfunc tp_iternext; */ 00146 00147 /*** Attribute descriptor and subclassing stuff ***/ 00148 bpy_lib_methods, /* struct PyMethodDef *tp_methods; */ 00149 NULL, /* struct PyMemberDef *tp_members; */ 00150 NULL, /* struct PyGetSetDef *tp_getset; */ 00151 NULL, /* struct _typeobject *tp_base; */ 00152 NULL, /* PyObject *tp_dict; */ 00153 NULL, /* descrgetfunc tp_descr_get; */ 00154 NULL, /* descrsetfunc tp_descr_set; */ 00155 offsetof(BPy_Library, dict),/* long tp_dictoffset; */ 00156 NULL, /* initproc tp_init; */ 00157 NULL, /* allocfunc tp_alloc; */ 00158 NULL, /* newfunc tp_new; */ 00159 /* Low-level free-memory routine */ 00160 NULL, /* freefunc tp_free; */ 00161 /* For PyObject_IS_GC */ 00162 NULL, /* inquiry tp_is_gc; */ 00163 NULL, /* PyObject *tp_bases; */ 00164 /* method resolution order */ 00165 NULL, /* PyObject *tp_mro; */ 00166 NULL, /* PyObject *tp_cache; */ 00167 NULL, /* PyObject *tp_subclasses; */ 00168 NULL, /* PyObject *tp_weaklist; */ 00169 NULL 00170 }; 00171 00172 PyDoc_STRVAR(bpy_lib_load_doc, 00173 ".. method:: load(filepath, link=False, relative=False)\n" 00174 "\n" 00175 " Returns a context manager which exposes 2 library objects on entering.\n" 00176 " Each object has attributes matching bpy.data which are lists of strings to be linked.\n" 00177 "\n" 00178 " :arg filepath: The path to a blend file.\n" 00179 " :type filepath: string\n" 00180 " :arg link: When False reference to the original file is lost.\n" 00181 " :type link: bool\n" 00182 " :arg relative: When True the path is stored relative to the open blend file.\n" 00183 " :type relative: bool\n" 00184 ); 00185 static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) 00186 { 00187 static const char *kwlist[] = {"filepath", "link", "relative", NULL}; 00188 BPy_Library *ret; 00189 const char* filename = NULL; 00190 int is_rel = 0, is_link = 0; 00191 00192 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ii:load", (char **)kwlist, &filename, &is_link, &is_rel)) 00193 return NULL; 00194 00195 ret = PyObject_New(BPy_Library, &bpy_lib_Type); 00196 00197 BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); 00198 BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); 00199 BLI_path_abs(ret->abspath, G.main->name); 00200 00201 ret->blo_handle = NULL; 00202 ret->flag= (is_link ? FILE_LINK : 0) | 00203 (is_rel ? FILE_RELPATH : 0); 00204 00205 ret->dict = PyDict_New(); 00206 00207 return (PyObject *)ret; 00208 } 00209 00210 static PyObject *_bpy_names(BPy_Library *self, int blocktype) 00211 { 00212 PyObject *list; 00213 LinkNode *l, *names; 00214 int totnames; 00215 00216 names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); 00217 00218 if (names) { 00219 int counter = 0; 00220 list = PyList_New(totnames); 00221 for (l = names; l; l = l->next) { 00222 PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); 00223 counter++; 00224 } 00225 BLI_linklist_free(names, free); /* free linklist *and* each node's data */ 00226 } 00227 else { 00228 list = PyList_New(0); 00229 } 00230 00231 return list; 00232 } 00233 00234 static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args)) 00235 { 00236 PyObject *ret; 00237 BPy_Library *self_from; 00238 PyObject *from_dict = PyDict_New(); 00239 ReportList reports; 00240 00241 BKE_reports_init(&reports, RPT_STORE); 00242 00243 self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports); 00244 00245 if (self->blo_handle == NULL) { 00246 if (BPy_reports_to_error(&reports, PyExc_IOError, TRUE) != -1) { 00247 PyErr_Format(PyExc_IOError, 00248 "load: %s failed to open blend file", 00249 self->abspath); 00250 } 00251 return NULL; 00252 } 00253 else { 00254 int i = 0, code; 00255 while ((code = BKE_idcode_iter_step(&i))) { 00256 if (BKE_idcode_is_linkable(code)) { 00257 const char *name_plural = BKE_idcode_to_name_plural(code); 00258 PyObject *str = PyUnicode_FromString(name_plural); 00259 PyDict_SetItem(self->dict, str, PyList_New(0)); 00260 PyDict_SetItem(from_dict, str, _bpy_names(self, code)); 00261 Py_DECREF(str); 00262 } 00263 } 00264 } 00265 00266 /* create a dummy */ 00267 self_from = PyObject_New(BPy_Library, &bpy_lib_Type); 00268 BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath)); 00269 BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath)); 00270 00271 self_from->blo_handle = NULL; 00272 self_from->flag = 0; 00273 self_from->dict = from_dict; /* owns the dict */ 00274 00275 /* return pair */ 00276 ret = PyTuple_New(2); 00277 00278 PyTuple_SET_ITEM(ret, 0, (PyObject *)self_from); 00279 00280 PyTuple_SET_ITEM(ret, 1, (PyObject *)self); 00281 Py_INCREF(self); 00282 00283 BKE_reports_clear(&reports); 00284 00285 return ret; 00286 } 00287 00288 static void bpy_lib_exit_warn_idname(BPy_Library *self, const char *name_plural, const char *idname) 00289 { 00290 PyObject *exc, *val, *tb; 00291 PyErr_Fetch(&exc, &val, &tb); 00292 if (PyErr_WarnFormat(PyExc_UserWarning, 1, 00293 "load: '%s' does not contain %s[\"%s\"]", 00294 self->abspath, name_plural, idname)) { 00295 /* Spurious errors can appear at shutdown */ 00296 if (PyErr_ExceptionMatches(PyExc_Warning)) { 00297 PyErr_WriteUnraisable((PyObject *)self); 00298 } 00299 } 00300 PyErr_Restore(exc, val, tb); 00301 } 00302 00303 static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item) 00304 { 00305 PyObject *exc, *val, *tb; 00306 PyErr_Fetch(&exc, &val, &tb); 00307 if (PyErr_WarnFormat(PyExc_UserWarning, 1, 00308 "load: '%s' expected a string type, not a %.200s", 00309 self->abspath, Py_TYPE(item)->tp_name)) { 00310 /* Spurious errors can appear at shutdown */ 00311 if (PyErr_ExceptionMatches(PyExc_Warning)) { 00312 PyErr_WriteUnraisable((PyObject *)self); 00313 } 00314 } 00315 PyErr_Restore(exc, val, tb); 00316 } 00317 00318 static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) 00319 { 00320 Main *bmain = CTX_data_main(BPy_GetContext()); 00321 Main *mainl = NULL; 00322 int err = 0; 00323 00324 flag_all_listbases_ids(LIB_PRE_EXISTING, 1); 00325 00326 /* here appending/linking starts */ 00327 mainl = BLO_library_append_begin(bmain, &(self->blo_handle), self->relpath); 00328 00329 { 00330 int i = 0, code; 00331 while ((code = BKE_idcode_iter_step(&i))) { 00332 if (BKE_idcode_is_linkable(code)) { 00333 const char *name_plural = BKE_idcode_to_name_plural(code); 00334 PyObject *ls = PyDict_GetItemString(self->dict, name_plural); 00335 // printf("lib: %s\n", name_plural); 00336 if (ls && PyList_Check(ls)) { 00337 /* loop */ 00338 Py_ssize_t size = PyList_GET_SIZE(ls); 00339 Py_ssize_t i; 00340 PyObject *item; 00341 const char *item_str; 00342 00343 for (i = 0; i < size; i++) { 00344 item = PyList_GET_ITEM(ls, i); 00345 item_str = _PyUnicode_AsString(item); 00346 00347 // printf(" %s\n", item_str); 00348 00349 if (item_str) { 00350 ID *id = BLO_library_append_named_part(mainl, &(self->blo_handle), item_str, code); 00351 if (id) { 00352 #ifdef USE_RNA_DATABLOCKS 00353 PointerRNA id_ptr; 00354 RNA_id_pointer_create(id, &id_ptr); 00355 Py_DECREF(item); 00356 item = pyrna_struct_CreatePyObject(&id_ptr); 00357 #endif 00358 } 00359 else { 00360 bpy_lib_exit_warn_idname(self, name_plural, item_str); 00361 /* just warn for now */ 00362 /* err = -1; */ 00363 #ifdef USE_RNA_DATABLOCKS 00364 item = Py_None; 00365 Py_INCREF(item); 00366 #endif 00367 } 00368 00369 /* ID or None */ 00370 } 00371 else { 00372 /* XXX, could complain about this */ 00373 bpy_lib_exit_warn_type(self, item); 00374 PyErr_Clear(); 00375 00376 #ifdef USE_RNA_DATABLOCKS 00377 item = Py_None; 00378 Py_INCREF(item); 00379 #endif 00380 } 00381 00382 #ifdef USE_RNA_DATABLOCKS 00383 PyList_SET_ITEM(ls, i, item); 00384 #endif 00385 } 00386 } 00387 } 00388 } 00389 } 00390 00391 if (err == -1) { 00392 /* exception raised above, XXX, this leaks some memory */ 00393 BLO_blendhandle_close(self->blo_handle); 00394 self->blo_handle = NULL; 00395 flag_all_listbases_ids(LIB_PRE_EXISTING, 0); 00396 return NULL; 00397 } 00398 else { 00399 Library *lib = mainl->curlib; /* newly added lib, assign before append end */ 00400 BLO_library_append_end(NULL, mainl, &(self->blo_handle), 0, self->flag); 00401 BLO_blendhandle_close(self->blo_handle); 00402 self->blo_handle = NULL; 00403 00404 { /* copied from wm_operator.c */ 00405 /* mark all library linked objects to be updated */ 00406 recalc_all_library_objects(G.main); 00407 00408 /* append, rather than linking */ 00409 if ((self->flag & FILE_LINK) == 0) { 00410 BKE_library_make_local(bmain, lib, 1); 00411 } 00412 } 00413 00414 flag_all_listbases_ids(LIB_PRE_EXISTING, 0); 00415 00416 Py_RETURN_NONE; 00417 } 00418 } 00419 00420 static PyObject *bpy_lib_dir(BPy_Library *self) 00421 { 00422 return PyDict_Keys(self->dict); 00423 } 00424 00425 00426 int bpy_lib_init(PyObject *mod_par) 00427 { 00428 static PyMethodDef load_meth = {"load", (PyCFunction)bpy_lib_load, 00429 METH_STATIC|METH_VARARGS|METH_KEYWORDS, 00430 bpy_lib_load_doc}; 00431 00432 PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL)); 00433 00434 /* some compilers dont like accessing this directly, delay assignment */ 00435 bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr; 00436 00437 if (PyType_Ready(&bpy_lib_Type) < 0) 00438 return -1; 00439 00440 return 0; 00441 }