Blender V2.61 - r43446

bpy.c

Go to the documentation of this file.
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 }