|
Blender
V2.59
|
00001 /* 00002 * $Id: bpy.c 38409 2011-07-15 04:01:47Z 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 00030 /* This file defines the '_bpy' module which is used by python's 'bpy' package. 00031 * a script writer should never directly access this module */ 00032 00033 #define WITH_PYTHON /* for AUD_PyInit.h, possibly others */ 00034 00035 #include <Python.h> 00036 00037 #include "bpy.h" 00038 #include "bpy_util.h" 00039 #include "bpy_rna.h" 00040 #include "bpy_app.h" 00041 #include "bpy_props.h" 00042 #include "bpy_operator.h" 00043 00044 #include "BLI_path_util.h" 00045 #include "BLI_string.h" 00046 #include "BLI_bpath.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "BKE_main.h" 00050 #include "BKE_global.h" /* XXX, G.main only */ 00051 #include "BKE_blender.h" 00052 00053 #include "RNA_access.h" 00054 00055 #include "MEM_guardedalloc.h" 00056 00057 /* external util modules */ 00058 #include "../generic/IDProp.h" 00059 #include "../generic/bgl.h" 00060 #include "../generic/blf_py_api.h" 00061 #include "../mathutils/mathutils.h" 00062 00063 PyObject *bpy_package_py= NULL; 00064 00065 PyDoc_STRVAR(bpy_script_paths_doc, 00066 ".. function:: script_paths()\n" 00067 "\n" 00068 " Return 2 paths to blender scripts directories.\n" 00069 "\n" 00070 " :return: (system, user) strings will be empty when not found.\n" 00071 " :rtype: tuple of strings\n" 00072 ); 00073 static PyObject *bpy_script_paths(PyObject *UNUSED(self)) 00074 { 00075 PyObject *ret= PyTuple_New(2); 00076 char *path; 00077 00078 path= BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL); 00079 PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(path?path:"")); 00080 path= BLI_get_folder(BLENDER_USER_SCRIPTS, NULL); 00081 PyTuple_SET_ITEM(ret, 1, PyUnicode_FromString(path?path:"")); 00082 00083 return ret; 00084 } 00085 00086 PyDoc_STRVAR(bpy_blend_paths_doc, 00087 ".. function:: blend_paths(absolute=False)\n" 00088 "\n" 00089 " Returns a list of paths to external files referenced by the loaded .blend file.\n" 00090 "\n" 00091 " :arg absolute: When true the paths returned are made absolute.\n" 00092 " :type absolute: boolean\n" 00093 " :return: path list.\n" 00094 " :rtype: list of strings\n" 00095 ); 00096 static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObject *kw) 00097 { 00098 struct BPathIterator *bpi; 00099 PyObject *list, *st; /* stupidly big string to be safe */ 00100 /* be sure there is low chance of the path being too short */ 00101 char filepath_expanded[1024]; 00102 const char *lib; 00103 00104 int absolute= 0; 00105 static const char *kwlist[]= {"absolute", NULL}; 00106 00107 if (!PyArg_ParseTupleAndKeywords(args, kw, "|i:blend_paths", (char **)kwlist, &absolute)) 00108 return NULL; 00109 00110 list= PyList_New(0); 00111 00112 for(BLI_bpathIterator_init(&bpi, G.main, G.main->name, 0); !BLI_bpathIterator_isDone(bpi); BLI_bpathIterator_step(bpi)) { 00113 /* build the list */ 00114 if (absolute) { 00115 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded); 00116 } 00117 else { 00118 lib= BLI_bpathIterator_getLib(bpi); 00119 if (lib && (BLI_path_cmp(lib, BLI_bpathIterator_getBasePath(bpi)))) { /* relative path to the library is NOT the same as our blendfile path, return an absolute path */ 00120 BLI_bpathIterator_getPathExpanded(bpi, filepath_expanded); 00121 } 00122 else { 00123 BLI_bpathIterator_getPath(bpi, filepath_expanded); 00124 } 00125 } 00126 st= PyUnicode_DecodeFSDefault(filepath_expanded); 00127 00128 PyList_Append(list, st); 00129 Py_DECREF(st); 00130 } 00131 00132 BLI_bpathIterator_free(bpi); 00133 00134 return list; 00135 } 00136 00137 00138 // PyDoc_STRVAR(bpy_user_resource_doc[]= // now in bpy/utils.py 00139 static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw) 00140 { 00141 char *type; 00142 char *subdir= NULL; 00143 int folder_id; 00144 static const char *kwlist[]= {"type", "subdir", NULL}; 00145 00146 char *path; 00147 00148 if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s:user_resource", (char **)kwlist, &type, &subdir)) 00149 return NULL; 00150 00151 /* stupid string compare */ 00152 if (!strcmp(type, "DATAFILES")) folder_id= BLENDER_USER_DATAFILES; 00153 else if(!strcmp(type, "CONFIG")) folder_id= BLENDER_USER_CONFIG; 00154 else if(!strcmp(type, "SCRIPTS")) folder_id= BLENDER_USER_SCRIPTS; 00155 else if(!strcmp(type, "AUTOSAVE")) folder_id= BLENDER_USER_AUTOSAVE; 00156 else { 00157 PyErr_SetString(PyExc_ValueError, "invalid resource argument"); 00158 return NULL; 00159 } 00160 00161 /* same logic as BLI_get_folder_create(), but best leave it up to the script author to create */ 00162 path= BLI_get_folder(folder_id, subdir); 00163 00164 if (!path) 00165 path= BLI_get_user_folder_notest(folder_id, subdir); 00166 00167 return PyUnicode_DecodeFSDefault(path ? path : ""); 00168 } 00169 00170 PyDoc_STRVAR(bpy_resource_path_doc, 00171 ".. function:: resource_path(type, major=2, minor=57)\n" 00172 "\n" 00173 " Return the base path for storing system files.\n" 00174 "\n" 00175 " :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n" 00176 " :type type: string\n" 00177 " :arg major: major version, defaults to current.\n" 00178 " :type major: int\n" 00179 " :arg minor: minor version, defaults to current.\n" 00180 " :type minor: string\n" 00181 " :return: the resource path (not necessarily existing).\n" 00182 " :rtype: string\n" 00183 ); 00184 static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObject *kw) 00185 { 00186 char *type; 00187 int major= BLENDER_VERSION/100, minor= BLENDER_VERSION%100; 00188 static const char *kwlist[]= {"type", "major", "minor", NULL}; 00189 int folder_id; 00190 char *path; 00191 00192 if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ii:resource_path", (char **)kwlist, &type, &major, &minor)) 00193 return NULL; 00194 00195 /* stupid string compare */ 00196 if (!strcmp(type, "USER")) folder_id= BLENDER_RESOURCE_PATH_USER; 00197 else if(!strcmp(type, "LOCAL")) folder_id= BLENDER_RESOURCE_PATH_LOCAL; 00198 else if(!strcmp(type, "SYSTEM")) folder_id= BLENDER_RESOURCE_PATH_SYSTEM; 00199 else { 00200 PyErr_SetString(PyExc_ValueError, "invalid resource argument"); 00201 return NULL; 00202 } 00203 00204 path= BLI_get_folder_version(folder_id, (major * 100) + minor, FALSE); 00205 00206 return PyUnicode_DecodeFSDefault(path); 00207 } 00208 00209 static PyMethodDef meth_bpy_script_paths= {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; 00210 static PyMethodDef meth_bpy_blend_paths= {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc}; 00211 static PyMethodDef meth_bpy_user_resource= {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS|METH_KEYWORDS, NULL}; 00212 static PyMethodDef meth_bpy_resource_path= {"resource_path", (PyCFunction)bpy_resource_path, METH_VARARGS|METH_KEYWORDS, bpy_resource_path_doc}; 00213 00214 00215 static PyObject *bpy_import_test(const char *modname) 00216 { 00217 PyObject *mod= PyImport_ImportModuleLevel((char *)modname, NULL, NULL, NULL, 0); 00218 if(mod) { 00219 Py_DECREF(mod); 00220 } 00221 else { 00222 PyErr_Print(); 00223 PyErr_Clear(); 00224 } 00225 00226 return mod; 00227 } 00228 00229 /***************************************************************************** 00230 * Description: Creates the bpy module and adds it to sys.modules for importing 00231 *****************************************************************************/ 00232 void BPy_init_modules(void) 00233 { 00234 extern BPy_StructRNA *bpy_context_module; 00235 extern int bpy_lib_init(PyObject *); 00236 PointerRNA ctx_ptr; 00237 PyObject *mod; 00238 00239 /* Needs to be first since this dir is needed for future modules */ 00240 char *modpath= BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules"); 00241 if(modpath) { 00242 // printf("bpy: found module path '%s'.\n", modpath); 00243 PyObject *sys_path= PySys_GetObject("path"); /* borrow */ 00244 PyObject *py_modpath= PyUnicode_FromString(modpath); 00245 PyList_Insert(sys_path, 0, py_modpath); /* add first */ 00246 Py_DECREF(py_modpath); 00247 } 00248 else { 00249 printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n"); 00250 } 00251 /* stand alone utility modules not related to blender directly */ 00252 IDProp_Init_Types(); /* not actually a submodule, just types */ 00253 00254 mod= PyModule_New("_bpy"); 00255 00256 /* add the module so we can import it */ 00257 PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod); 00258 Py_DECREF(mod); 00259 00260 /* run first, initializes rna types */ 00261 BPY_rna_init(); 00262 00263 PyModule_AddObject(mod, "types", BPY_rna_types()); /* needs to be first so bpy_types can run */ 00264 PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); /* metaclass for idprop types, bpy_types.py needs access */ 00265 00266 bpy_lib_init(mod); /* adds '_bpy._library_load', must be called before 'bpy_types' which uses it */ 00267 00268 bpy_import_test("bpy_types"); 00269 PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ 00270 bpy_import_test("bpy_types"); 00271 PyModule_AddObject(mod, "props", BPY_rna_props()); 00272 PyModule_AddObject(mod, "ops", BPY_operator_module()); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ 00273 PyModule_AddObject(mod, "app", BPY_app_struct()); 00274 00275 /* bpy context */ 00276 RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); 00277 bpy_context_module= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr); 00278 /* odd that this is needed, 1 ref on creation and another for the module 00279 * but without we get a crash on exit */ 00280 Py_INCREF(bpy_context_module); 00281 00282 PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); 00283 00284 /* utility func's that have nowhere else to go */ 00285 PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL)); 00286 PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL)); 00287 PyModule_AddObject(mod, meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); 00288 PyModule_AddObject(mod, meth_bpy_resource_path.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL)); 00289 00290 /* register funcs (bpy_rna.c) */ 00291 PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL)); 00292 PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL)); 00293 00294 /* add our own modules dir, this is a python package */ 00295 bpy_package_py= bpy_import_test("bpy"); 00296 }