From ecdd332021dcafdec69525a5140c1f43e1dc434a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 1 Apr 2009 22:02:22 +0000 Subject: forgot to add bpy_panel_wrap.c --- source/blender/python/intern/bpy_panel_wrap.c | 222 ++++++++++++++++++++++++++ source/blender/python/intern/bpy_ui.c | 4 +- 2 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 source/blender/python/intern/bpy_panel_wrap.c (limited to 'source/blender/python/intern') diff --git a/source/blender/python/intern/bpy_panel_wrap.c b/source/blender/python/intern/bpy_panel_wrap.c new file mode 100644 index 00000000000..044ac3eefdb --- /dev/null +++ b/source/blender/python/intern/bpy_panel_wrap.c @@ -0,0 +1,222 @@ +/** + * $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 ***** + */ + +#include "bpy_panel_wrap.h" +#include "bpy_rna.h" +#include "bpy_util.h" +#include "bpy_compat.h" + +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "BLI_listbase.h" +#include "BKE_context.h" +#include "BKE_screen.h" +#include "DNA_screen_types.h" +#include "MEM_guardedalloc.h" +#include "ED_screen.h" + +#define PYPANEL_ATTR_UINAME "__label__" +#define PYPANEL_ATTR_IDNAME "__name__" /* use pythons class name */ +#define PYPANEL_ATTR_CONTEXT "__context__" + +#define PYPANEL_DRAW 1 +#define PYPANEL_POLL 2 + +static int PyPanel_generic(int mode, const bContext *C, Panel *pnl) +{ + PyObject *py_class= (PyObject *)(pnl->type->py_data); + //uiLayout *layout= pnl->layout; + + PyObject *args; + PyObject *ret= NULL, *py_class_instance, *item; + int ret_flag= 0; + + PyGILState_STATE gilstate = PyGILState_Ensure(); + + args = PyTuple_New(0); + 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 */ + PointerRNA context_ptr; + + if (mode==PYPANEL_DRAW) { + item= PyObject_GetAttrString(py_class, "draw"); + } + else if (mode==PYPANEL_POLL) { + item= PyObject_GetAttrString(py_class, "poll"); + } + args = PyTuple_New(2); + PyTuple_SET_ITEM(args, 0, py_class_instance); + + RNA_pointer_create(NULL, &RNA_Context, (void *)C, &context_ptr); + + PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&context_ptr)); + + ret = PyObject_Call(item, args, NULL); + + Py_DECREF(args); + Py_DECREF(item); + } + + if (ret == NULL) { /* covers py_class_instance failing too */ + PyErr_Print(); /* XXX use reporting api? */ + } + else { + if (mode==PYPANEL_POLL) { + if (PyBool_Check(ret) == 0) { + PyErr_SetString(PyExc_ValueError, "Python poll function return value "); + PyErr_Print(); /* XXX use reporting api? */ + } + else { + ret_flag= ret==Py_True ? 1:0; + } + } + else { + //XXX - draw stuff + } + + Py_DECREF(ret); + } + PyGILState_Release(gilstate); + + return ret_flag; +} + +static void PyPanel_draw(const bContext *C, Panel *pnl) +{ + PyPanel_generic(PYPANEL_DRAW, C, pnl); +} + +static int PyPanel_poll(const bContext *C) +{ + //return PyPanel_generic(PYPANEL_POLL, C, NULL); + return 1; // XXX we need the panel type to access the PyObject grr! +} + +/* pyOperators - Operators defined IN Python */ +PyObject *PyPanel_wrap_add(PyObject *self, PyObject *args) +{ + PyObject *item; + PyObject *py_class; + char *space_identifier; + char *region_identifier; + int space_value; + int region_value; + + PanelType *pt; + SpaceType *st; + ARegionType *art; + + static struct BPY_class_attr_check pypnl_class_attr_values[]= { + {PYPANEL_ATTR_IDNAME, 's', 0, 0}, + {PYPANEL_ATTR_UINAME, 's', 0, 0}, + {PYPANEL_ATTR_CONTEXT, 's', 0, 0}, + {"draw", 'f', 2, 0}, /* Do we need the Panel struct?, could be an extra arg */ + {"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL}, + {NULL, 0, 0, 0}}; + + enum { + PYPANEL_ATTR_IDNAME_IDX=0, + PYPANEL_ATTR_UINAME_IDX, + PYPANEL_ATTR_CONTEXT_IDX, + PYPANEL_ATTR_DRAW_IDX, + PYPANEL_ATTR_POLL_IDX + }; + + PyObject *pypnl_class_attrs[6]= {NULL, NULL, NULL, NULL, NULL, NULL}; + + if( !PyArg_ParseTuple( args, "Oss:addPanel", &py_class, &space_identifier, ®ion_identifier)) + return NULL; + + /* Should this use a base class? */ + if (BPY_class_validate("Panel", py_class, NULL, pypnl_class_attr_values, pypnl_class_attrs) < 0) { + return NULL; /* BPY_class_validate sets the error */ + } + + if (RNA_enum_value_from_id(space_type_items, space_identifier, &space_value)==0) { + char *cstring= BPy_enum_as_string(space_type_items); + PyErr_Format( PyExc_AttributeError, "SpaceType \"%s\" is not one of [%s]", space_identifier, cstring); + MEM_freeN(cstring); + return NULL; + } + + if (RNA_enum_value_from_id(region_type_items, region_identifier, ®ion_value)==0) { + char *cstring= BPy_enum_as_string(region_type_items); + PyErr_Format( PyExc_AttributeError, "RegionType \"%s\" is not one of [%s]", region_identifier, cstring); + MEM_freeN(cstring); + return NULL; + } + + st= BKE_spacetype_from_id(space_value); + +#if 0 + // for printing what panels we have + for(art= st->regiontypes.first; art; art= art->next) { + + printf("REG %d\n", art->regionid); + + for(pt= art->paneltypes.first; pt; pt= pt->next) { + printf("\tREG %s %s - %s\n", pt->idname, pt->name, pt->context); + } + } +#endif + + for(art= st->regiontypes.first; art; art= art->next) { + if (art->regionid==region_value) + break; + } + + if (art==NULL) { + PyErr_Format( PyExc_AttributeError, "SpaceType \"%s\" does not have a UI region '%s'", space_identifier, region_identifier); + return NULL; + } + + pt= MEM_callocN(sizeof(PanelType), "python buttons panel"); + pt->idname= _PyUnicode_AsString(pypnl_class_attrs[PYPANEL_ATTR_IDNAME_IDX]); + + item= pypnl_class_attrs[PYPANEL_ATTR_UINAME_IDX]; + pt->name= item ? _PyUnicode_AsString(item):pt->idname; + + pt->context= _PyUnicode_AsString(pypnl_class_attrs[PYPANEL_ATTR_CONTEXT_IDX]); + + if (pypnl_class_attrs[PYPANEL_ATTR_POLL_IDX]) + pt->poll= PyPanel_poll; + + pt->draw= PyPanel_draw; + + Py_INCREF(py_class); + pt->py_data= (void *)py_class; + + BLI_addtail(&art->paneltypes, pt); + Py_RETURN_NONE; +} + +PyObject *PyPanel_wrap_remove(PyObject *self, PyObject *args) +{ + // XXX - todo + Py_RETURN_NONE; +} + diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c index e1054cd1a45..608086843ba 100644 --- a/source/blender/python/intern/bpy_ui.c +++ b/source/blender/python/intern/bpy_ui.c @@ -427,8 +427,8 @@ static struct PyMethodDef ui_methods[] = { {"getWindowPtr", (PyCFunction)Method_getWindowPtr, METH_NOARGS, ""}, /* Adding panels should be moved, at the moment there is no obvious place as there is with operators */ - // XXX missing file {"addPanel", (PyCFunction)PyPanel_wrap_add, METH_VARARGS, ""}, - // XXX missing file {"removePanel", (PyCFunction)PyPanel_wrap_remove, METH_VARARGS, ""}, + {"addPanel", (PyCFunction)PyPanel_wrap_add, METH_VARARGS, ""}, + {"removePanel", (PyCFunction)PyPanel_wrap_remove, METH_VARARGS, ""}, {NULL, NULL, 0, NULL} }; -- cgit v1.2.3