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-04-01 16:43:07 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-04-01 16:43:07 +0400
commit3224efc38419201b44503982541aca8eaeb29486 (patch)
tree77a09bed4e1668427c48ceac7fdb8021eaa7f729 /source
parent3a28a7450596f46281431bd163b9a237eb481055 (diff)
Python Panels WIP
- Register python panels - Added a generic class checking function BPY_class_validate() for panels/operators. - No button drawing yet Brecht, Added RNA_enum_value_from_id() and RNA_enum_id_from_value() to rna_access.c to do lookups between identifiers and values of EnumPropertyItem's, Not sure if these should go here.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/context.c1
-rw-r--r--source/blender/blenkernel/intern/screen.c15
-rw-r--r--source/blender/editors/include/ED_mesh.h1
-rw-r--r--source/blender/makesrna/RNA_access.h4
-rw-r--r--source/blender/makesrna/RNA_enum_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_access.c26
-rw-r--r--source/blender/makesrna/intern/rna_screen.c8
-rw-r--r--source/blender/makesrna/intern/rna_space.c42
-rw-r--r--source/blender/python/BPY_extern.h3
-rw-r--r--source/blender/python/intern/bpy_interface.c5
-rw-r--r--source/blender/python/intern/bpy_operator.c2
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c (renamed from source/blender/python/intern/bpy_opwrapper.c)174
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h (renamed from source/blender/python/intern/bpy_opwrapper.h)4
-rw-r--r--source/blender/python/intern/bpy_panel_wrap.h36
-rw-r--r--source/blender/python/intern/bpy_rna.c15
-rw-r--r--source/blender/python/intern/bpy_ui.c6
-rw-r--r--source/blender/python/intern/bpy_util.c89
-rw-r--r--source/blender/python/intern/bpy_util.h21
18 files changed, 300 insertions, 154 deletions
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 47622611cb9..9d2830983e1 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -41,7 +41,6 @@
#include "BKE_context.h"
#include "BKE_main.h"
-#include "BKE_report.h"
#include "BKE_screen.h"
#include <string.h>
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 483876e5e05..2f3ca52a09e 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -56,7 +56,22 @@ static void spacetype_free(SpaceType *st)
for(art= st->regiontypes.first; art; art= art->next) {
BLI_freelistN(&art->drawcalls);
+#ifdef DISABLE_PYTHON
BLI_freelistN(&art->paneltypes);
+#else
+ {
+ PanelType *pnl, *pnl_next;
+ for(pnl= art->paneltypes.first; pnl; pnl= pnl_next) {
+ pnl_next= pnl->next;
+
+ if(pnl->py_data)
+ BPY_DECREF(pnl->py_data);
+
+ MEM_freeN(pnl);
+ }
+ art->paneltypes.first= art->paneltypes.last= NULL;
+ }
+#endif
BLI_freelistN(&art->headertypes);
}
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 53b50460d1d..35706308ed7 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -43,6 +43,7 @@ struct bDeformGroup;
struct MDeformWeight;
struct MDeformVert;
struct Scene;
+struct Mesh;
struct MCol;
struct UvVertMap;
struct UvMapVert;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index cde4c4d6867..1bc898016e6 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -456,6 +456,10 @@ int RNA_enum_get(PointerRNA *ptr, const char *name);
void RNA_enum_set(PointerRNA *ptr, const char *name, int value);
int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname);
+/* lower level functions that donr use a PointerRNA */
+int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value);
+int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier);
+
void RNA_string_get(PointerRNA *ptr, const char *name, char *value);
char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen);
int RNA_string_length(PointerRNA *ptr, const char *name);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 9cb49fcaf60..f8c0ba18c29 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -30,6 +30,8 @@
/* Types */
extern EnumPropertyItem prop_mode_items[];
+extern EnumPropertyItem space_type_items[];
+extern EnumPropertyItem region_type_items[];
#endif /* RNA_ENUM_TYPES */
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 52b1b77ddf0..cf6072c2bfd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1832,6 +1832,32 @@ int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
}
}
+int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value)
+{
+ for( ; item->identifier; item++) {
+ if (strcmp(item->identifier, identifier)==0) {
+ *value= item->value;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier)
+{
+ for( ; item->identifier; item++) {
+ if (item->value==value) {
+ *identifier= item->identifier;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
{
PropertyRNA *prop= RNA_struct_find_property(ptr, name);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 9508357233c..00cf29bfc51 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -32,6 +32,14 @@
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+EnumPropertyItem region_type_items[] = {
+ {RGN_TYPE_WINDOW, "WINDOW", "Window", ""},
+ {RGN_TYPE_HEADER, "HEADER", "Header", ""},
+ {RGN_TYPE_CHANNELS, "CHANNELS", "Channels", ""},
+ {RGN_TYPE_TEMPORARY, "TEMPORARY", "Temporary", ""},
+ {RGN_TYPE_UI, "BUTTONS_WINDOW", "Window", ""},
+ {0, NULL, NULL, NULL}};
+
#ifdef RNA_RUNTIME
#else
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 5184e904927..9950d70af24 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -33,6 +33,26 @@
#include "WM_types.h"
+EnumPropertyItem space_type_items[] = {
+ {SPACE_EMPTY, "EMPTY", "Empty", ""},
+ {SPACE_VIEW3D, "VIEW_3D", "3D View", ""},
+ {SPACE_IPO, "GRAPH_EDITOR", "Graph Editor", ""},
+ {SPACE_OUTLINER, "OUTLINER", "Outliner", ""},
+ {SPACE_BUTS, "BUTTONS_WINDOW", "Buttons Window", ""},
+ {SPACE_FILE, "FILE_BROWSER", "File Browser", ""},
+ {SPACE_IMAGE, "IMAGE_EDITOR", "Image Editor", ""},
+ {SPACE_INFO, "USER_PREFERENCES", "User Preferences", ""},
+ {SPACE_SEQ, "SEQUENCE_EDITOR", "Sequence Editor", ""},
+ {SPACE_TEXT, "TEXT_EDITOR", "Text Editor", ""},
+ //{SPACE_IMASEL, "IMAGE_BROWSER", "Image Browser", ""},
+ {SPACE_SOUND, "AUDIO_WINDOW", "Audio Window", ""},
+ {SPACE_ACTION, "DOPESHEET_EDITOR", "DopeSheet Editor", ""},
+ {SPACE_NLA, "NLA_EDITOR", "NLA Editor", ""},
+ {SPACE_SCRIPT, "SCRIPTS_WINDOW", "Scripts Window", ""},
+ {SPACE_TIME, "TIMELINE", "Timeline", ""},
+ {SPACE_NODE, "NODE_EDITOR", "Node Editor", ""},
+ {0, NULL, NULL, NULL}};
+
#ifdef RNA_RUNTIME
#include "DNA_scene_types.h"
@@ -117,26 +137,6 @@ static void rna_def_space(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
- static EnumPropertyItem type_items[] = {
- {SPACE_EMPTY, "EMPTY", "Empty", ""},
- {SPACE_VIEW3D, "VIEW_3D", "3D View", ""},
- {SPACE_IPO, "GRAPH_EDITOR", "Graph Editor", ""},
- {SPACE_OUTLINER, "OUTLINER", "Outliner", ""},
- {SPACE_BUTS, "BUTTONS_WINDOW", "Buttons Window", ""},
- {SPACE_FILE, "FILE_BROWSER", "File Browser", ""},
- {SPACE_IMAGE, "IMAGE_EDITOR", "Image Editor", ""},
- {SPACE_INFO, "USER_PREFERENCES", "User Preferences", ""},
- {SPACE_SEQ, "SEQUENCE_EDITOR", "Sequence Editor", ""},
- {SPACE_TEXT, "TEXT_EDITOR", "Text Editor", ""},
- //{SPACE_IMASEL, "IMAGE_BROWSER", "Image Browser", ""},
- {SPACE_SOUND, "AUDIO_WINDOW", "Audio Window", ""},
- {SPACE_ACTION, "DOPESHEET_EDITOR", "DopeSheet Editor", ""},
- {SPACE_NLA, "NLA_EDITOR", "NLA Editor", ""},
- {SPACE_SCRIPT, "SCRIPTS_WINDOW", "Scripts Window", ""},
- {SPACE_TIME, "TIMELINE", "Timeline", ""},
- {SPACE_NODE, "NODE_EDITOR", "Node Editor", ""},
- {0, NULL, NULL, NULL}};
srna= RNA_def_struct(brna, "Space", NULL);
RNA_def_struct_sdna(srna, "SpaceLink");
@@ -145,7 +145,7 @@ static void rna_def_space(BlenderRNA *brna)
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "spacetype");
- RNA_def_property_enum_items(prop, type_items);
+ RNA_def_property_enum_items(prop, space_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Type", "Space data type.");
}
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 4b7238a2f7c..690dc7144e6 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -139,7 +139,8 @@ extern "C" {
void BPY_scripts_clear_pyobjects( void );
void error_pyscript( void );
-
+ void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
+
/* void BPY_Err_Handle(struct Text *text); */
/* void BPY_clear_bad_scriptlink(struct ID *id, struct Text *byebye); */
/* void BPY_clear_bad_scriptlist(struct ListBase *, struct Text *byebye); */
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 94ec8deebe4..f8031368f06 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -241,6 +241,11 @@ int BPY_run_script_space_listener(bContext *C, SpaceScript * sc)
return 1;
}
+void BPY_DECREF(void *pyob_ptr)
+{
+ Py_DECREF((PyObject *)pyob_ptr);
+}
+
#if 0
/* called from the the scripts window, assume context is ok */
int BPY_run_python_script_space(const char *modulename, const char *func)
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 02f4723c037..29ec3376765 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -24,7 +24,7 @@
*/
#include "bpy_operator.h"
-#include "bpy_opwrapper.h"
+#include "bpy_operator_wrap.h"
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_compat.h"
diff --git a/source/blender/python/intern/bpy_opwrapper.c b/source/blender/python/intern/bpy_operator_wrap.c
index b7d4c82588e..1db1f547fa6 100644
--- a/source/blender/python/intern/bpy_opwrapper.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -24,7 +24,7 @@
*/
-#include "bpy_opwrapper.h"
+#include "bpy_operator_wrap.h"
#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -45,14 +45,6 @@
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
-typedef struct PyOperatorType {
- void *next, *prev;
- char idname[OP_MAX_TYPENAME];
- char name[OP_MAX_TYPENAME];
- char description[OP_MAX_TYPENAME]; // XXX should be longer?
- PyObject *py_class;
-} PyOperatorType;
-
static PyObject *pyop_dict_from_event(wmEvent *event)
{
PyObject *dict= PyDict_New();
@@ -191,14 +183,16 @@ static struct BPY_flag_def pyop_ret_flags[] = {
static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *event)
{
- PyOperatorType *pyot = op->type->pyop_data;
+ PyObject *py_class = op->type->pyop_data;
PyObject *args;
PyObject *ret= NULL, *py_class_instance, *item;
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
-
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
args = PyTuple_New(1);
- PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(pyot->py_class, "__rna__")); // need to use an rna instance as the first arg
- py_class_instance = PyObject_Call(pyot->py_class, args, NULL);
+ PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(py_class, "__rna__")); // need to use an rna instance as the first arg
+ py_class_instance = PyObject_Call(py_class, args, NULL);
Py_DECREF(args);
if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
@@ -229,16 +223,16 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
if (mode==PYOP_INVOKE) {
- item= PyObject_GetAttrString(pyot->py_class, "invoke");
+ item= PyObject_GetAttrString(py_class, "invoke");
args = PyTuple_New(2);
PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
}
else if (mode==PYOP_EXEC) {
- item= PyObject_GetAttrString(pyot->py_class, "exec");
+ item= PyObject_GetAttrString(py_class, "exec");
args = PyTuple_New(1);
}
else if (mode==PYOP_POLL) {
- item= PyObject_GetAttrString(pyot->py_class, "poll");
+ item= PyObject_GetAttrString(py_class, "poll");
args = PyTuple_New(2);
//XXX Todo - wrap context in a useful way, None for now.
PyTuple_SET_ITEM(args, 1, Py_None);
@@ -251,7 +245,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
Py_DECREF(item);
}
- if (ret == NULL) {
+ if (ret == NULL) { /* covers py_class_instance failing too */
pyop_error_report(op->reports);
}
else {
@@ -280,6 +274,8 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
Py_DECREF(ret);
}
+ PyGILState_Release(gilstate);
+
return ret_flag;
}
@@ -302,15 +298,29 @@ static int PYTHON_OT_poll(bContext *C)
void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
{
- PyOperatorType *pyot = (PyOperatorType *)userdata;
- PyObject *py_class = pyot->py_class;
+ PyObject *py_class = (PyObject *)userdata;
PyObject *props, *item;
/* identifiers */
- ot->name= pyot->name;
- ot->idname= pyot->idname;
- ot->description= pyot->description;
+ item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
+ Py_DECREF(item);
+ ot->idname= _PyUnicode_AsString(item);
+
+ item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME);
+ if (item) {
+ Py_DECREF(item);
+ ot->name= _PyUnicode_AsString(item);
+ }
+ else {
+ ot->name= ot->idname;
+ PyErr_Clear();
+ }
+
+ item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION);
+ Py_DECREF(item);
+ ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"";
+
/* api callbacks, detailed checks dont on adding */
if (PyObject_HasAttrString(py_class, "invoke"))
ot->invoke= PYTHON_OT_invoke;
@@ -364,105 +374,48 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
/* pyOperators - Operators defined IN Python */
-PyObject *PYOP_wrap_add(PyObject *self, PyObject *value)
+PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
{
- PyObject *optype, *item;
+ PyObject *base_class, *item;
- PyOperatorType *pyot;
- char *idname= NULL;
- char *name= NULL;
- char *description= NULL;
- static char *pyop_func_names[] = {"exec", "invoke", "poll", NULL};
- static int pyop_func_nargs[] = {1, 2, 2, 0};
-
- PyObject *pyargcount;
- int i, argcount;
-
+ char *idname= NULL;
+ int i;
+
+ static struct BPY_class_attr_check pyop_class_attr_values[]= {
+ {PYOP_ATTR_IDNAME, 's', 0, 0},
+ {PYOP_ATTR_UINAME, 's', 0, BPY_CLASS_ATTR_OPTIONAL},
+ {PYOP_ATTR_PROP, 'l', 0, BPY_CLASS_ATTR_OPTIONAL},
+ {PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
+ {"exec", 'f', 1, BPY_CLASS_ATTR_OPTIONAL},
+ {"invoke", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
+ {"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
+ {NULL, 0, 0, 0}
+ };
// in python would be...
//PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator");
- optype = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator");
- Py_DECREF(optype);
+ base_class = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator");
+ Py_DECREF(base_class);
-
- if (!PyObject_IsSubclass(value, optype)) {
- PyErr_SetString( PyExc_AttributeError, "expected Operator subclass of bpy.types.Operator");
- return NULL;
+ if(BPY_class_validate("Operator", py_class, base_class, pyop_class_attr_values, NULL) < 0) {
+ return NULL; /* BPY_class_validate sets the error */
}
-
+
/* class name is used for operator ID - this can be changed later if we want */
- item = PyObject_GetAttrString(value, PYOP_ATTR_IDNAME);
+ item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
Py_DECREF(item);
idname = _PyUnicode_AsString(item);
-
if (WM_operatortype_find(idname)) {
PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname);
return NULL;
}
- /* Operator user readible name */
- item = PyObject_GetAttrString(value, PYOP_ATTR_UINAME);
- if (item) {
- Py_DECREF(item);
- name = _PyUnicode_AsString(item);
- }
- if (name == NULL) {
- name = idname;
- PyErr_Clear();
- }
-
- /* use py docstring for description, should always be None or a string */
- item = PyObject_GetAttrString(value, PYOP_ATTR_DESCRIPTION);
- Py_DECREF(item);
-
- if (PyUnicode_Check(item)) {
- description = _PyUnicode_AsString(item);
- }
- else {
- description = "";
- }
-
- /* Check known functions and argument lengths */
- for (i=0; pyop_func_names[i]; i++) {
-
- item=PyObject_GetAttrString(value, pyop_func_names[i]);
- if (item) {
- Py_DECREF(item);
-
- /* check its callable */
- if (!PyFunction_Check(item)) {
- PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.%s() is not a function", idname, pyop_func_names[i]);
- return NULL;
- }
- /* check the number of args is correct */
- /* MyClass.exec.func_code.co_argcount */
-
- pyargcount = PyObject_GetAttrString(PyFunction_GET_CODE(item), "co_argcount");
- Py_DECREF(pyargcount);
- argcount = PyLong_AsSsize_t(pyargcount);
-
- if (argcount != pyop_func_nargs[i]) {
- PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.%s() takes %d args, should be %d", idname, pyop_func_names[i], argcount, pyop_func_nargs[i]);
- return NULL;
- }
-
- } else {
- PyErr_Clear();
- }
- }
-
/* If we have properties set, check its a list of dicts */
- item = PyObject_GetAttrString(value, PYOP_ATTR_PROP);
+ item= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP);
if (item) {
Py_DECREF(item);
-
- if (!PyList_Check(item)) {
- PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must be a list", idname);
- return NULL;
- }
-
for(i=0; i<PyList_Size(item); i++) {
PyObject *py_args = PyList_GET_ITEM(item, i);
PyObject *py_func_ptr, *py_kw; /* place holders */
@@ -477,24 +430,18 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *value)
PyErr_Clear();
}
- pyot= MEM_callocN(sizeof(PyOperatorType), "PyOperatorType");
-
- strncpy(pyot->idname, idname, sizeof(pyot->idname));
- strncpy(pyot->name, name, sizeof(pyot->name));
- strncpy(pyot->description, description, sizeof(pyot->description));
- pyot->py_class= value;
- Py_INCREF(value);
-
- WM_operatortype_append_ptr(PYTHON_OT_wrapper, pyot);
+ Py_INCREF(py_class);
+ WM_operatortype_append_ptr(PYTHON_OT_wrapper, py_class);
Py_RETURN_NONE;
}
PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
{
+ PyObject *py_class;
char *idname= NULL;
wmOperatorType *ot;
- PyOperatorType *pyot;
+
if (PyUnicode_Check(value))
idname = _PyUnicode_AsString(value);
@@ -514,13 +461,12 @@ PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
return NULL;
}
- if (!(pyot= (PyOperatorType *)ot->pyop_data)) {
+ if (!(py_class= (PyObject *)ot->pyop_data)) {
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" was not created by python", idname);
return NULL;
}
- Py_XDECREF(pyot->py_class);
- MEM_freeN(pyot);
+ Py_XDECREF(py_class);
WM_operatortype_remove(idname);
diff --git a/source/blender/python/intern/bpy_opwrapper.h b/source/blender/python/intern/bpy_operator_wrap.h
index 04120a81517..2929d57ab82 100644
--- a/source/blender/python/intern/bpy_opwrapper.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -22,8 +22,8 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef BPY_OPWRAPPER_H
-#define BPY_OPWRAPPER_H
+#ifndef BPY_OPERATOR_WRAP_H
+#define BPY_OPERATOR_WRAP_H
#include <Python.h>
diff --git a/source/blender/python/intern/bpy_panel_wrap.h b/source/blender/python/intern/bpy_panel_wrap.h
new file mode 100644
index 00000000000..42b24703d00
--- /dev/null
+++ b/source/blender/python/intern/bpy_panel_wrap.h
@@ -0,0 +1,36 @@
+
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BPY_PANEL_WRAP_H
+#define BPY_PANEL_WRAP_H
+
+#include <Python.h>
+
+/* these are used for operator methods, used by bpy_operator.c */
+
+PyObject *PyPanel_wrap_add(PyObject *self, PyObject *args);
+PyObject *PyPanel_wrap_remove(PyObject *self, PyObject *args);
+
+#endif
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 23eed552a2a..20ca134c67e 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -128,20 +128,9 @@ static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
{
const EnumPropertyItem *item;
int totitem, i;
-
- DynStr *dynstr= BLI_dynstr_new();
- char *cstring;
-
- RNA_property_enum_items(ptr, prop, &item, &totitem);
-
- for (i=0; i<totitem; i++) {
-
- BLI_dynstr_appendf(dynstr, i?", '%s'":"'%s'", item[i].identifier);
- }
- cstring = BLI_dynstr_get_cstring(dynstr);
- BLI_dynstr_free(dynstr);
- return cstring;
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+ return BPy_enum_as_string(item);
}
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
index 7b3b4c01c55..608086843ba 100644
--- a/source/blender/python/intern/bpy_ui.c
+++ b/source/blender/python/intern/bpy_ui.c
@@ -27,6 +27,8 @@
#include "bpy_rna.h" /* for rna buttons */
#include "bpy_operator.h" /* for setting button operator properties */
#include "bpy_compat.h"
+#include "bpy_panel_wrap.h" /* for setting button operator properties */
+
#include "WM_types.h" /* for WM_OP_INVOKE_DEFAULT & friends */
#include "BLI_dynstr.h"
@@ -423,6 +425,10 @@ static struct PyMethodDef ui_methods[] = {
{"getScreenPtr", (PyCFunction)Method_getScreenPtr, METH_NOARGS, ""},
{"getSpacePtr", (PyCFunction)Method_getSpacePtr, METH_NOARGS, ""},
{"getWindowPtr", (PyCFunction)Method_getWindowPtr, METH_NOARGS, ""},
+
+ /* Adding panels should be moved, at the moment there is no obvious place as there is with operators */
+ {"addPanel", (PyCFunction)PyPanel_wrap_add, METH_VARARGS, ""},
+ {"removePanel", (PyCFunction)PyPanel_wrap_remove, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index 7979ca9cd37..347b914a030 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -26,7 +26,6 @@
#include "bpy_util.h"
#include "BLI_dynstr.h"
#include "MEM_guardedalloc.h"
-#include "bpy_compat.h"
PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag)
{
@@ -241,3 +240,91 @@ PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
return item;
}
+
+
+int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
+{
+ PyObject *item;
+ PyObject *py_arg_count;
+ int i, arg_count;
+
+ if (base_class) {
+ if (!PyObject_IsSubclass(class, base_class)) {
+ PyObject *name= PyObject_GetAttrString(base_class, "__name__");
+ PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
+ Py_XDECREF(name);
+ return -1;
+ }
+ }
+
+ for(i= 0;class_attrs->name; class_attrs++, i++) {
+ item = PyObject_GetAttrString(class, class_attrs->name);
+
+ if (py_class_attrs)
+ py_class_attrs[i]= item;
+
+ if (item==NULL) {
+ if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
+ return -1;
+ }
+
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(item); /* no need to keep a ref, the class owns it */
+
+ if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
+ /* dont do anything, this is ok, dont bother checking other types */
+ }
+ else {
+ switch(class_attrs->type) {
+ case 's':
+ if (PyUnicode_Check(item)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
+ return -1;
+ }
+ break;
+ case 'l':
+ if (PyList_Check(item)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a list", class_type, class_attrs->name);
+ return -1;
+ }
+ break;
+ case 'f':
+ if (PyFunction_Check(item)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
+ return -1;
+ }
+ if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
+ py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(item), "co_argcount");
+ arg_count = PyLong_AsSsize_t(py_arg_count);
+ Py_DECREF(py_arg_count);
+
+ if (arg_count != class_attrs->arg_count) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
+ return -1;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+char *BPy_enum_as_string(EnumPropertyItem *item)
+{
+ DynStr *dynstr= BLI_dynstr_new();
+ EnumPropertyItem *e;
+ char *cstring;
+
+ for (e= item; item->identifier; item++) {
+ BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
+ }
+
+ cstring = BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+ return cstring;
+}
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index 51e13f98a35..e2bea331b0e 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -28,6 +28,9 @@
#define BPY_UTIL_H
#include "bpy_compat.h"
+#include "RNA_types.h" /* for EnumPropertyItem only */
+
+struct EnumPropertyItem;
/* for internal use only, so python can interchange a sequence of strings with flags */
typedef struct BPY_flag_def {
@@ -46,4 +49,22 @@ void BPY_getFileAndNum(char **filename, int *lineno);
/* own python like utility function */
PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
+
+
+/* Class type checking, use for checking classes can be added as operators, panels etc */
+typedef struct BPY_class_attr_check {
+ const char *name; /* name of the class attribute */
+ char type; /* 's' = string, 'f' = function, 'l' = list, (add as needed) */
+ int arg_count; /* only for function types, -1 for undefined, includes self arg */
+ int flag; /* other options */
+} BPY_class_attr_check;
+
+/* BPY_class_attr_check, flag */
+#define BPY_CLASS_ATTR_OPTIONAL 1
+#define BPY_CLASS_ATTR_NONE_OK 2
+
+int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs);
+
+char *BPy_enum_as_string(struct EnumPropertyItem *item);
+
#endif