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