merge with 2.5 at r22793
This commit is contained in:
@@ -14,8 +14,6 @@
|
||||
#include "compile.h" /* for the PyCodeObject */
|
||||
#include "eval.h" /* for PyEval_EvalCode */
|
||||
|
||||
#include "bpy_compat.h"
|
||||
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_operator.h"
|
||||
#include "bpy_ui.h"
|
||||
@@ -45,6 +43,80 @@
|
||||
#include "../generic/BGL.h"
|
||||
|
||||
|
||||
/* for internal use, when starting and ending python scripts */
|
||||
|
||||
/* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
|
||||
static int py_call_level= 0;
|
||||
|
||||
|
||||
// only for tests
|
||||
#define TIME_PY_RUN
|
||||
|
||||
#ifdef TIME_PY_RUN
|
||||
#include "PIL_time.h"
|
||||
static int bpy_timer_count = 0;
|
||||
static double bpy_timer; /* time since python starts */
|
||||
static double bpy_timer_run; /* time for each python script run */
|
||||
static double bpy_timer_run_tot; /* accumulate python runs */
|
||||
#endif
|
||||
|
||||
void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
|
||||
{
|
||||
py_call_level++;
|
||||
|
||||
if(gilstate)
|
||||
*gilstate = PyGILState_Ensure();
|
||||
|
||||
if(py_call_level==1) {
|
||||
|
||||
BPY_update_modules(); /* can give really bad results if this isnt here */
|
||||
|
||||
if(C) { // XXX - should always be true.
|
||||
BPy_SetContext(C);
|
||||
bpy_import_main_set(CTX_data_main(C));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "ERROR: Python context called with a NULL Context. this should not happen!\n");
|
||||
}
|
||||
|
||||
#ifdef TIME_PY_RUN
|
||||
if(bpy_timer_count==0) {
|
||||
/* record time from the beginning */
|
||||
bpy_timer= PIL_check_seconds_timer();
|
||||
bpy_timer_run = bpy_timer_run_tot = 0.0;
|
||||
}
|
||||
bpy_timer_run= PIL_check_seconds_timer();
|
||||
|
||||
|
||||
bpy_timer_count++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void bpy_context_clear(bContext *C, PyGILState_STATE *gilstate)
|
||||
{
|
||||
py_call_level--;
|
||||
|
||||
if(gilstate)
|
||||
PyGILState_Release(*gilstate);
|
||||
|
||||
if(py_call_level < 0) {
|
||||
fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
|
||||
}
|
||||
else if(py_call_level==0) {
|
||||
// XXX - Calling classes currently wont store the context :\, cant set NULL because of this. but this is very flakey still.
|
||||
//BPy_SetContext(NULL);
|
||||
//bpy_import_main_set(NULL);
|
||||
|
||||
#ifdef TIME_PY_RUN
|
||||
bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run;
|
||||
bpy_timer_count++;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BPY_free_compiled_text( struct Text *text )
|
||||
{
|
||||
if( text->compiled ) {
|
||||
@@ -75,23 +147,22 @@ static void bpy_init_modules( void )
|
||||
|
||||
|
||||
/* stand alone utility modules not related to blender directly */
|
||||
Geometry_Init("Geometry");
|
||||
Mathutils_Init("Mathutils");
|
||||
BGL_Init("BGL");
|
||||
Geometry_Init();
|
||||
Mathutils_Init();
|
||||
BGL_Init();
|
||||
}
|
||||
|
||||
#if (PY_VERSION_HEX < 0x02050000)
|
||||
PyObject *PyImport_ImportModuleLevel(char *name, void *a, void *b, void *c, int d)
|
||||
{
|
||||
return PyImport_ImportModule(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BPY_update_modules( void )
|
||||
{
|
||||
#if 0 // slow, this runs all the time poll, draw etc 100's of time a sec.
|
||||
PyObject *mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
|
||||
PyModule_AddObject( mod, "data", BPY_rna_module() );
|
||||
PyModule_AddObject( mod, "types", BPY_rna_types() );
|
||||
PyModule_AddObject( mod, "types", BPY_rna_types() ); // atm this does not need updating
|
||||
#endif
|
||||
|
||||
/* refreshes the main struct */
|
||||
BPY_update_rna_module();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -106,9 +177,6 @@ static PyObject *CreateGlobalDictionary( bContext *C )
|
||||
PyDict_SetItemString( dict, "__name__", item );
|
||||
Py_DECREF(item);
|
||||
|
||||
// XXX - evil, need to access context
|
||||
BPy_SetContext(C);
|
||||
|
||||
// XXX - put somewhere more logical
|
||||
{
|
||||
PyMethodDef *ml;
|
||||
@@ -173,9 +241,10 @@ void BPY_start_python( int argc, char **argv )
|
||||
|
||||
Py_Initialize( );
|
||||
|
||||
#if (PY_VERSION_HEX < 0x03000000)
|
||||
PySys_SetArgv( argc, argv);
|
||||
#else
|
||||
/*convert argv to wchar_t*/
|
||||
// PySys_SetArgv( argc, argv); // broken in py3, not a huge deal
|
||||
|
||||
/*temporarily set argv*/
|
||||
/* sigh, why do python guys not have a char** version anymore? :( */
|
||||
{
|
||||
int i;
|
||||
@@ -187,7 +256,6 @@ void BPY_start_python( int argc, char **argv )
|
||||
PySys_SetObject("argv", py_argv);
|
||||
Py_DECREF(py_argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize thread support (also acquires lock) */
|
||||
PyEval_InitThreads();
|
||||
@@ -205,38 +273,57 @@ void BPY_start_python( int argc, char **argv )
|
||||
PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item);
|
||||
}
|
||||
|
||||
pyrna_alloc_types();
|
||||
|
||||
py_tstate = PyGILState_GetThisThreadState();
|
||||
PyEval_ReleaseThread(py_tstate);
|
||||
}
|
||||
|
||||
void BPY_end_python( void )
|
||||
{
|
||||
// fprintf(stderr, "Ending Python!\n");
|
||||
|
||||
PyGILState_Ensure(); /* finalizing, no need to grab the state */
|
||||
|
||||
// free other python data.
|
||||
//BPY_rna_free_types();
|
||||
pyrna_free_types();
|
||||
|
||||
/* clear all python data from structs */
|
||||
|
||||
Py_Finalize( );
|
||||
|
||||
return;
|
||||
#ifdef TIME_PY_RUN
|
||||
// measure time since py started
|
||||
bpy_timer = PIL_check_seconds_timer() - bpy_timer;
|
||||
|
||||
printf("*bpy stats* - ");
|
||||
printf("tot exec: %d, ", bpy_timer_count);
|
||||
printf("tot run: %.4fsec, ", bpy_timer_run_tot);
|
||||
if(bpy_timer_count>0)
|
||||
printf("average run: %.6fsec, ", (bpy_timer_run_tot/bpy_timer_count));
|
||||
|
||||
if(bpy_timer>0.0)
|
||||
printf("tot usage %.4f%%", (bpy_timer_run_tot/bpy_timer)*100.0);
|
||||
|
||||
printf("\n");
|
||||
|
||||
// fprintf(stderr, "Ending Python Done!\n");
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Can run a file or text block */
|
||||
int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
|
||||
{
|
||||
PyObject *py_dict, *py_result;
|
||||
PyObject *py_dict, *py_result= NULL;
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
if (fn==NULL && text==NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//BPY_start_python();
|
||||
|
||||
gilstate = PyGILState_Ensure();
|
||||
|
||||
BPY_update_modules(); /* can give really bad results if this isnt here */
|
||||
bpy_import_main_set(CTX_data_main(C));
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
py_dict = CreateGlobalDictionary(C);
|
||||
|
||||
@@ -251,13 +338,11 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
|
||||
MEM_freeN( buf );
|
||||
|
||||
if( PyErr_Occurred( ) ) {
|
||||
BPy_errors_to_report(reports);
|
||||
BPY_free_compiled_text( text );
|
||||
PyGILState_Release(gilstate);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict );
|
||||
if(text->compiled)
|
||||
py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict );
|
||||
|
||||
} else {
|
||||
#if 0
|
||||
@@ -287,10 +372,9 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
|
||||
}
|
||||
|
||||
Py_DECREF(py_dict);
|
||||
PyGILState_Release(gilstate);
|
||||
bpy_import_main_set(NULL);
|
||||
|
||||
//BPY_end_python();
|
||||
bpy_context_clear(C, &gilstate);
|
||||
|
||||
return py_result ? 1:0;
|
||||
}
|
||||
|
||||
@@ -473,12 +557,7 @@ void BPY_run_ui_scripts(bContext *C, int reload)
|
||||
PyGILState_STATE gilstate;
|
||||
PyObject *sys_path;
|
||||
|
||||
gilstate = PyGILState_Ensure();
|
||||
|
||||
// XXX - evil, need to access context
|
||||
BPy_SetContext(C);
|
||||
bpy_import_main_set(CTX_data_main(C));
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
sys_path= PySys_GetObject("path"); /* borrow */
|
||||
PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
|
||||
@@ -537,12 +616,14 @@ void BPY_run_ui_scripts(bContext *C, int reload)
|
||||
|
||||
PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
|
||||
|
||||
bpy_import_main_set(NULL);
|
||||
bpy_context_clear(C, &gilstate);
|
||||
|
||||
PyGILState_Release(gilstate);
|
||||
#ifdef TIME_REGISTRATION
|
||||
printf("script time %f\n", (PIL_check_seconds_timer()-time));
|
||||
#endif
|
||||
|
||||
/* reset the timer so as not to take loading into the stats */
|
||||
bpy_timer_count = 0;
|
||||
}
|
||||
|
||||
/* ****************************************** */
|
||||
@@ -740,3 +821,56 @@ float BPY_pydriver_eval (ChannelDriver *driver)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int BPY_button_eval(bContext *C, char *expr, double *value)
|
||||
{
|
||||
PyGILState_STATE gilstate;
|
||||
PyObject *dict, *retval;
|
||||
int error_ret = 0;
|
||||
|
||||
if (!value || !expr || expr[0]=='\0') return -1;
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
dict= CreateGlobalDictionary(C);
|
||||
retval = PyRun_String(expr, Py_eval_input, dict, dict);
|
||||
|
||||
if (retval == NULL) {
|
||||
error_ret= -1;
|
||||
}
|
||||
else {
|
||||
double val;
|
||||
|
||||
if(PyTuple_Check(retval)) {
|
||||
/* Users my have typed in 10km, 2m
|
||||
* add up all values */
|
||||
int i;
|
||||
val= 0.0;
|
||||
|
||||
for(i=0; i<PyTuple_GET_SIZE(retval); i++) {
|
||||
val+= PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
val = PyFloat_AsDouble(retval);
|
||||
}
|
||||
Py_DECREF(retval);
|
||||
|
||||
if(val==-1 && PyErr_Occurred()) {
|
||||
error_ret= -1;
|
||||
}
|
||||
else {
|
||||
*value= val;
|
||||
}
|
||||
}
|
||||
|
||||
if(error_ret) {
|
||||
BPy_errors_to_report(CTX_wm_reports(C));
|
||||
}
|
||||
|
||||
Py_DECREF(dict);
|
||||
bpy_context_clear(C, &gilstate);
|
||||
|
||||
return error_ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user