Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-10-29 12:25:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-10-29 12:25:11 +0300
commitc508e6198a614619bb9d82cd59c0fdb7f55f427d (patch)
treebda1b4de7fbc1ef951f4bf49dfd440086902613a /source
parent40731af9d0b85e3cf93e46e48b814faa06aac74b (diff)
Python can now run operators with their own context (data context).
The aim of this is to avoid having to set the selection each time before running an operator from python. At the moment this is set as a python dictionary with string keys and rna values... eg. C = {} C["active_object"] = bpy.data.objects['SomeOb'] bpy.ops.object.game_property_new(C) # ofcourse this works too.. bpy.ops.object.game_property_new({"active_object":ob}) # or... C = {"main":bpy.data, "scene":bpy.data.scenes[0], "active_object":bpy.data.objects['SomeOb'], "selected_editable_objects":list(bpy.data.objects)} bpy.ops.object.location_apply(C)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_context.h3
-rw-r--r--source/blender/blenkernel/intern/context.c14
-rw-r--r--source/blender/makesrna/intern/rna_curve.c4
-rw-r--r--source/blender/python/intern/bpy_interface.c55
-rw-r--r--source/blender/python/intern/bpy_operator.c93
5 files changed, 128 insertions, 41 deletions
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 09e13c2930e..feba39ee11d 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -124,6 +124,9 @@ void CTX_store_free_list(ListBase *contexts);
int CTX_py_init_get(bContext *C);
void CTX_py_init_set(bContext *C, int value);
+void *CTX_py_dict_get(bContext *C);
+void CTX_py_dict_set(bContext *C, void *value);
+
/* Window Manager Context */
struct wmWindowManager *CTX_wm_manager(const bContext *C);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index d5cc31d918a..7f2872c0797 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -71,6 +71,7 @@ struct bContext {
int recursion;
int py_init; /* true if python is initialized */
+ void *py_context;
} data;
/* data evaluation */
@@ -175,6 +176,15 @@ void CTX_py_init_set(bContext *C, int value)
C->data.py_init= value;
}
+void *CTX_py_dict_get(bContext *C)
+{
+ return C->data.py_context;
+}
+void CTX_py_dict_set(bContext *C, void *value)
+{
+ C->data.py_context= value;
+}
+
/* window manager context */
wmWindowManager *CTX_wm_manager(const bContext *C)
@@ -401,6 +411,10 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res
memset(result, 0, sizeof(bContextDataResult));
+ if(CTX_py_dict_get(C)) {
+ return bpy_context_get(C, member, result);
+ }
+
/* we check recursion to ensure that we do not get infinite
* loops requesting data from ourselfs in a context callback */
if(!done && recursion < 1 && C->wm.store) {
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 1f1caeaa9b5..995be6d5023 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -757,12 +757,12 @@ static void rna_def_curve(BlenderRNA *brna)
prop= RNA_def_property(srna, "render_resolution_u", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "resolu_ren");
- RNA_def_property_ui_range(prop, 1, 1024, 1, 0);
+ RNA_def_property_ui_range(prop, 0, 1024, 1, 0);
RNA_def_property_ui_text(prop, "Render Resolution U", "Surface resolution in U direction used while rendering. Zero skips this property.");
prop= RNA_def_property(srna, "render_resolution_v", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "resolv_ren");
- RNA_def_property_ui_range(prop, 1, 1024, 1, 0);
+ RNA_def_property_ui_range(prop, 0, 1024, 1, 0);
RNA_def_property_ui_text(prop, "Render Resolution V", "Surface resolution in V direction used while rendering. Zero skips this property.");
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 53c0d591437..dc7f6947f38 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -63,6 +63,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_text.h"
+#include "BKE_context.h"
#include "BPY_extern.h"
@@ -948,3 +949,57 @@ int BPY_button_eval(bContext *C, char *expr, double *value)
return error_ret;
}
+
+
+int bpy_context_get(bContext *C, const char *member, bContextDataResult *result)
+{
+ PyObject *pyctx= (PyObject *)CTX_py_dict_get(C);
+ PyObject *item= PyDict_GetItemString(pyctx, member);
+ PointerRNA *ptr= NULL;
+ int done= 0;
+
+ if(item==NULL) {
+ /* pass */
+ }
+ else if(item==Py_None) {
+ /* pass */
+ }
+ else if(BPy_StructRNA_Check(item)) {
+ ptr= &(((BPy_StructRNA *)item)->ptr);
+
+ //result->ptr= ((BPy_StructRNA *)item)->ptr;
+ CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
+ done= 1;
+ }
+ else if (PyList_Check(item)) {
+ int len= PyList_Size(item);
+ int i;
+ for(i = 0; i < len; i++) {
+ PyObject *list_item = PyList_GET_ITEM(item, i); // XXX check type
+
+ if(BPy_StructRNA_Check(list_item)) {
+ /*
+ CollectionPointerLink *link= MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get");
+ link->ptr= ((BPy_StructRNA *)item)->ptr;
+ BLI_addtail(&result->list, link);
+ */
+ ptr= &(((BPy_StructRNA *)list_item)->ptr);
+ CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
+ }
+ else {
+ printf("List item not a valid type\n");
+ }
+
+ }
+
+ done= 1;
+ }
+
+ if(done==0) {
+ if (item) printf("Context '%s' not found\n", member);
+ else printf("Context '%s' not a valid type\n", member);
+ }
+
+ return done;
+}
+
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 87752ca9c58..1ae0a40ce16 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -48,6 +48,8 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
char *opname;
PyObject *kw= NULL; /* optional args */
+ PyObject *context_dict= NULL; /* optional args */
+ PyObject *context_dict_back;
/* note that context is an int, python does the conversion in this case */
int context= WM_OP_EXEC_DEFAULT;
@@ -55,7 +57,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
bContext *C = BPy_GetContext();
- if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.call", &opname, &PyDict_Type, &kw, &context))
+ if (!PyArg_ParseTuple(args, "sO|O!i:bpy.__ops__.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
@@ -65,61 +67,74 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
return NULL;
}
+ if(!PyDict_Check(context_dict))
+ context_dict= NULL;
+
+ context_dict_back= CTX_py_dict_get(C);
+
+ CTX_py_dict_set(C, (void *)context_dict);
+ Py_XINCREF(context_dict); /* so we done loose it */
+
if(WM_operator_poll((bContext*)C, ot) == FALSE) {
PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect");
- return NULL;
+ error_val= -1;
}
+ else {
+ /* WM_operator_properties_create(&ptr, opname); */
+ /* Save another lookup */
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
- /* WM_operator_properties_create(&ptr, opname); */
- /* Save another lookup */
- RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
-
- if(kw && PyDict_Size(kw))
- error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
+ if(kw && PyDict_Size(kw))
+ error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
-
- if (error_val==0) {
- ReportList *reports;
- reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
- BKE_reports_init(reports, RPT_STORE);
+ if (error_val==0) {
+ ReportList *reports;
- WM_operator_call_py(C, ot, context, &ptr, reports);
+ reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
+ BKE_reports_init(reports, RPT_STORE);
- if(BPy_reports_to_error(reports))
- error_val = -1;
+ WM_operator_call_py(C, ot, context, &ptr, reports);
- /* operator output is nice to have in the terminal/console too */
- if(reports->list.first) {
- char *report_str= BKE_reports_string(reports, 0); /* all reports */
+ if(BPy_reports_to_error(reports))
+ error_val = -1;
- if(report_str) {
- PySys_WriteStdout("%s\n", report_str);
- MEM_freeN(report_str);
+ /* operator output is nice to have in the terminal/console too */
+ if(reports->list.first) {
+ char *report_str= BKE_reports_string(reports, 0); /* all reports */
+
+ if(report_str) {
+ PySys_WriteStdout("%s\n", report_str);
+ MEM_freeN(report_str);
+ }
+ }
+
+ BKE_reports_clear(reports);
+ if ((reports->flag & RPT_FREE) == 0)
+ {
+ MEM_freeN(reports);
}
}
- BKE_reports_clear(reports);
- if ((reports->flag & RPT_FREE) == 0)
- {
- MEM_freeN(reports);
- }
- }
-
- WM_operator_properties_free(&ptr);
+ WM_operator_properties_free(&ptr);
#if 0
- /* if there is some way to know an operator takes args we should use this */
- {
- /* no props */
- if (kw != NULL) {
- PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
- return NULL;
- }
+ /* if there is some way to know an operator takes args we should use this */
+ {
+ /* no props */
+ if (kw != NULL) {
+ PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
+ return NULL;
+ }
- WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
- }
+ WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
+ }
#endif
+ }
+
+ /* restore with original context dict, probably NULL but need this for nested operator calls */
+ Py_XDECREF(context_dict);
+ CTX_py_dict_set(C, (void *)context_dict_back);
if (error_val==-1) {
return NULL;