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