Bevel mod: cleanup flags and extra data.
[blender.git] / source / blender / python / intern / bpy_app.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup pythonintern
19  *
20  * This file defines a 'PyStructSequence' accessed via 'bpy.app', mostly
21  * exposing static applications variables such as version and buildinfo
22  * however some writable variables have been added such as 'debug' and 'tempdir'
23  */
24
25
26 #include <Python.h>
27
28 #include "bpy_app.h"
29
30 #include "bpy_app_alembic.h"
31 #include "bpy_app_ffmpeg.h"
32 #include "bpy_app_ocio.h"
33 #include "bpy_app_oiio.h"
34 #include "bpy_app_opensubdiv.h"
35 #include "bpy_app_openvdb.h"
36 #include "bpy_app_sdl.h"
37 #include "bpy_app_build_options.h"
38
39 #include "bpy_app_translations.h"
40
41 #include "bpy_app_handlers.h"
42 #include "bpy_driver.h"
43
44 /* modules */
45 #include "bpy_app_icons.h"
46 #include "bpy_app_timers.h"
47
48 #include "BLI_utildefines.h"
49
50 #include "BKE_appdir.h"
51 #include "BKE_blender_version.h"
52 #include "BKE_global.h"
53 #include "BKE_library_override.h"
54
55 #include "DNA_ID.h"
56
57 #include "UI_interface_icons.h"
58
59 /* for notifiers */
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63 #include "../generic/py_capi_utils.h"
64 #include "../generic/python_utildefines.h"
65
66 #ifdef BUILD_DATE
67 extern char build_date[];
68 extern char build_time[];
69 extern unsigned long build_commit_timestamp;
70 extern char build_commit_date[];
71 extern char build_commit_time[];
72 extern char build_hash[];
73 extern char build_branch[];
74 extern char build_platform[];
75 extern char build_type[];
76 extern char build_cflags[];
77 extern char build_cxxflags[];
78 extern char build_linkflags[];
79 extern char build_system[];
80 #endif
81
82 static PyTypeObject BlenderAppType;
83
84 static PyStructSequence_Field app_info_fields[] = {
85         {(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
86         {(char *)"version_string", (char *)"The Blender version formatted as a string"},
87         {(char *)"version_char", (char *)"The Blender version character (for minor releases)"},
88         {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
89         {(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"},
90         {(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"},
91         {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"},
92
93         /* buildinfo */
94         {(char *)"build_date", (char *)"The date this blender instance was built"},
95         {(char *)"build_time", (char *)"The time this blender instance was built"},
96         {(char *)"build_commit_timestamp", (char *)"The unix timestamp of commit this blender instance was built"},
97         {(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"},
98         {(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"},
99         {(char *)"build_hash", (char *)"The commit hash this blender instance was built with"},
100         {(char *)"build_branch", (char *)"The branch this blender instance was built from"},
101         {(char *)"build_platform", (char *)"The platform this blender instance was built for"},
102         {(char *)"build_type", (char *)"The type of build (Release, Debug)"},
103         {(char *)"build_cflags", (char *)"C compiler flags"},
104         {(char *)"build_cxxflags", (char *)"C++ compiler flags"},
105         {(char *)"build_linkflags", (char *)"Binary linking flags"},
106         {(char *)"build_system", (char *)"Build system used"},
107
108         /* submodules */
109         {(char *)"alembic", (char *)"Alembic library information backend"},
110         {(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
111         {(char *)"ocio", (char *)"OpenColorIO library information backend"},
112         {(char *)"oiio", (char *)"OpenImageIO library information backend"},
113         {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
114         {(char *)"openvdb", (char *)"OpenVDB library information backend"},
115         {(char *)"sdl", (char *)"SDL library information backend"},
116         {(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
117         {(char *)"handlers", (char *)"Application handler callbacks"},
118         {(char *)"translations", (char *)"Application and addons internationalization API"},
119
120         /* Modules (not struct sequence). */
121         {(char *)"icons", (char *)"Manage custom icons"},
122         {(char *)"timers", (char *)"Manage timers"},
123         {NULL},
124 };
125
126 PyDoc_STRVAR(bpy_app_doc,
127 "This module contains application values that remain unchanged during runtime.\n"
128 "\n"
129 "Submodules:\n"
130 "\n"
131 ".. toctree::\n"
132 "   :maxdepth: 1\n"
133 "\n"
134 "   bpy.app.handlers.rst\n"
135 "   bpy.app.icons.rst\n"
136 "   bpy.app.timers.rst\n"
137 "   bpy.app.translations.rst\n"
138 );
139
140 static PyStructSequence_Desc app_info_desc = {
141         (char *)"bpy.app",     /* name */
142         bpy_app_doc,    /* doc */
143         app_info_fields,    /* fields */
144         ARRAY_SIZE(app_info_fields) - 1,
145 };
146
147 static PyObject *make_app_info(void)
148 {
149         PyObject *app_info;
150         int pos = 0;
151
152         app_info = PyStructSequence_New(&BlenderAppType);
153         if (app_info == NULL) {
154                 return NULL;
155         }
156 #define SetIntItem(flag) \
157         PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
158 #define SetStrItem(str) \
159         PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
160 #define SetBytesItem(str) \
161         PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
162 #define SetObjItem(obj) \
163         PyStructSequence_SET_ITEM(app_info, pos++, obj)
164
165         SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
166         SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)",
167                                         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
168
169         SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
170         SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
171         SetStrItem(BKE_appdir_program_path());
172         SetObjItem(PyBool_FromLong(G.background));
173         SetObjItem(PyBool_FromLong(G.factory_startup));
174
175         /* build info, use bytes since we can't assume _any_ encoding:
176          * see patch [#30154] for issue */
177 #ifdef BUILD_DATE
178         SetBytesItem(build_date);
179         SetBytesItem(build_time);
180         SetIntItem(build_commit_timestamp);
181         SetBytesItem(build_commit_date);
182         SetBytesItem(build_commit_time);
183         SetBytesItem(build_hash);
184         SetBytesItem(build_branch);
185         SetBytesItem(build_platform);
186         SetBytesItem(build_type);
187         SetBytesItem(build_cflags);
188         SetBytesItem(build_cxxflags);
189         SetBytesItem(build_linkflags);
190         SetBytesItem(build_system);
191 #else
192         SetBytesItem("Unknown");
193         SetBytesItem("Unknown");
194         SetIntItem(0);
195         SetBytesItem("Unknown");
196         SetBytesItem("Unknown");
197         SetBytesItem("Unknown");
198         SetBytesItem("Unknown");
199         SetBytesItem("Unknown");
200         SetBytesItem("Unknown");
201         SetBytesItem("Unknown");
202         SetBytesItem("Unknown");
203         SetBytesItem("Unknown");
204         SetBytesItem("Unknown");
205 #endif
206
207         SetObjItem(BPY_app_alembic_struct());
208         SetObjItem(BPY_app_ffmpeg_struct());
209         SetObjItem(BPY_app_ocio_struct());
210         SetObjItem(BPY_app_oiio_struct());
211         SetObjItem(BPY_app_opensubdiv_struct());
212         SetObjItem(BPY_app_openvdb_struct());
213         SetObjItem(BPY_app_sdl_struct());
214         SetObjItem(BPY_app_build_options_struct());
215         SetObjItem(BPY_app_handlers_struct());
216         SetObjItem(BPY_app_translations_struct());
217
218         /* modules */
219         SetObjItem(BPY_app_icons_module());
220         SetObjItem(BPY_app_timers_module());
221
222 #undef SetIntItem
223 #undef SetStrItem
224 #undef SetBytesItem
225 #undef SetObjItem
226
227         if (PyErr_Occurred()) {
228                 Py_CLEAR(app_info);
229                 return NULL;
230         }
231         return app_info;
232 }
233
234 /* a few getsets because it makes sense for them to be in bpy.app even though
235  * they are not static */
236
237 PyDoc_STRVAR(bpy_app_debug_doc,
238 "Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"
239 );
240 static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *closure)
241 {
242         const int flag = POINTER_AS_INT(closure);
243         return PyBool_FromLong(G.debug & flag);
244 }
245
246 static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *closure)
247 {
248         const int flag = POINTER_AS_INT(closure);
249         const int param = PyObject_IsTrue(value);
250
251         if (param == -1) {
252                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
253                 return -1;
254         }
255
256         if (param)  G.debug |=  flag;
257         else        G.debug &= ~flag;
258
259         return 0;
260 }
261
262 PyDoc_STRVAR(bpy_app_global_flag_doc,
263 "Boolean, for application behavior (started with --enable-* matching this attribute name)"
264 );
265 static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure)
266 {
267         const int flag = POINTER_AS_INT(closure);
268         return PyBool_FromLong(G.f & flag);
269 }
270
271 static int bpy_app_global_flag_set(PyObject *UNUSED(self), PyObject *value, void *closure)
272 {
273         const int flag = POINTER_AS_INT(closure);
274         const int param = PyObject_IsTrue(value);
275
276         if (param == -1) {
277                 PyErr_SetString(PyExc_TypeError, "bpy.app.use_* can only be True/False");
278                 return -1;
279         }
280
281         if (param)  G.f |=  flag;
282         else        G.f &= ~flag;
283
284         return 0;
285 }
286
287 static int bpy_app_global_flag_set__only_disable(PyObject *UNUSED(self), PyObject *value, void *closure)
288 {
289         const int param = PyObject_IsTrue(value);
290         if (param == 1) {
291                 PyErr_SetString(PyExc_ValueError, "This bpy.app.use_* option can only be disabled");
292                 return -1;
293         }
294         return bpy_app_global_flag_set(NULL, value, closure);
295 }
296
297 #define BROKEN_BINARY_PATH_PYTHON_HACK
298
299 PyDoc_STRVAR(bpy_app_binary_path_python_doc,
300 "String, the path to the python executable (read-only)"
301 );
302 static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure))
303 {
304         /* refcount is held in BlenderAppType.tp_dict */
305         static PyObject *ret = NULL;
306
307         if (ret == NULL) {
308                 /* only run once */
309                 char fullpath[1024];
310                 BKE_appdir_program_python_search(
311                         fullpath, sizeof(fullpath),
312                         PY_MAJOR_VERSION, PY_MINOR_VERSION);
313                 ret = PyC_UnicodeFromByte(fullpath);
314 #ifdef BROKEN_BINARY_PATH_PYTHON_HACK
315                 Py_INCREF(ret);
316                 UNUSED_VARS(self);
317 #else
318                 PyDict_SetItem(BlenderAppType.tp_dict, /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), ret);
319 #endif
320         }
321         else {
322                 Py_INCREF(ret);
323         }
324
325         return ret;
326 }
327
328 PyDoc_STRVAR(bpy_app_debug_value_doc,
329 "Short, number which can be set to non-zero values for testing purposes"
330 );
331 static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure))
332 {
333         return PyLong_FromLong(G.debug_value);
334 }
335
336 static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
337 {
338         short param = PyC_Long_AsI16(value);
339
340         if (param == -1 && PyErr_Occurred()) {
341                 PyC_Err_SetString_Prefix(
342                         PyExc_TypeError,
343                         "bpy.app.debug_value can only be set to a whole number");
344                 return -1;
345         }
346
347         G.debug_value = param;
348
349         WM_main_add_notifier(NC_WINDOW, NULL);
350
351         return 0;
352 }
353
354 PyDoc_STRVAR(bpy_app_tempdir_doc,
355 "String, the temp directory used by blender (read-only)"
356 );
357 static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
358 {
359         return PyC_UnicodeFromByte(BKE_tempdir_session());
360 }
361
362 PyDoc_STRVAR(bpy_app_driver_dict_doc,
363 "Dictionary for drivers namespace, editable in-place, reset on file load (read-only)"
364 );
365 static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure))
366 {
367         if (bpy_pydriver_Dict == NULL) {
368                 if (bpy_pydriver_create_dict() != 0) {
369                         PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary");
370                         return NULL;
371                 }
372         }
373
374         return Py_INCREF_RET(bpy_pydriver_Dict);
375 }
376
377 PyDoc_STRVAR(bpy_app_preview_render_size_doc,
378 "Reference size for icon/preview renders (read-only)"
379 );
380 static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
381 {
382         return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure)));
383 }
384
385 static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
386 {
387         return PyC_UnicodeFromByte(G.autoexec_fail);
388 }
389
390
391 PyDoc_STRVAR(bpy_app_use_static_override_doc,
392 "Boolean, whether static override is exposed in UI or not."
393 );
394 static PyObject *bpy_app_use_static_override_get(PyObject *UNUSED(self), void *UNUSED(closure))
395 {
396         return PyBool_FromLong((long)BKE_override_static_is_enabled());
397 }
398
399 static int bpy_app_use_static_override_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
400 {
401         const int param = PyC_Long_AsBool(value);
402
403         if (param == -1 && PyErr_Occurred()) {
404                 PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean");
405                 return -1;
406         }
407
408         BKE_override_static_enable((const bool)param);
409
410         return 0;
411 }
412
413
414 static PyGetSetDef bpy_app_getsets[] = {
415         {(char *)"debug",           bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
416         {(char *)"debug_ffmpeg",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
417         {(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE},
418         {(char *)"debug_python",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
419         {(char *)"debug_events",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
420         {(char *)"debug_handlers",  bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
421         {(char *)"debug_wm",        bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
422         {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
423         {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD},
424         {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL},
425         {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG},
426         {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME},
427         {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY},
428         {(char *)"debug_simdata",   bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
429         {(char *)"debug_gpumem",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
430         {(char *)"debug_io",        bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_IO},
431
432         {(char *)"use_static_override", bpy_app_use_static_override_get, bpy_app_use_static_override_set, (char *)bpy_app_use_static_override_doc, NULL},
433         {(char *)"use_event_simulate", bpy_app_global_flag_get, bpy_app_global_flag_set__only_disable, (char *)bpy_app_global_flag_doc, (void *)G_FLAG_EVENT_SIMULATE},
434
435         {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL},
436
437         {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
438         {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
439         {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
440
441         {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
442         {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
443
444         /* security */
445         {(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL},
446         {(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET},
447         {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
448         {NULL, NULL, NULL, NULL, NULL},
449 };
450
451 static void py_struct_seq_getset_init(void)
452 {
453         /* tricky dynamic members, not to py-spec! */
454         for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
455                 PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
456                 PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
457                 Py_DECREF(item);
458         }
459 }
460 /* end dynamic bpy.app */
461
462
463 PyObject *BPY_app_struct(void)
464 {
465         PyObject *ret;
466
467         PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
468
469         ret = make_app_info();
470
471         /* prevent user from creating new instances */
472         BlenderAppType.tp_init = NULL;
473         BlenderAppType.tp_new = NULL;
474         BlenderAppType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
475
476         /* kindof a hack ontop of PyStructSequence */
477         py_struct_seq_getset_init();
478
479         return ret;
480 }