diff options
author | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
---|---|---|
committer | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
commit | 12315f4d0e0ae993805f141f64cb8c73c5297311 (patch) | |
tree | 59b45827cd8293cfb727758989c7a74b40183974 /source/blender/bpython |
Initial revisionv2.25
Diffstat (limited to 'source/blender/bpython')
39 files changed, 12538 insertions, 0 deletions
diff --git a/source/blender/bpython/Makefile b/source/blender/bpython/Makefile new file mode 100644 index 00000000000..ef58948bd88 --- /dev/null +++ b/source/blender/bpython/Makefile @@ -0,0 +1,37 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# 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. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# Bounces make to subdirectories. + +SOURCEDIR = source/blender/bpython +DIRS = intern + +include nan_subdirs.mk diff --git a/source/blender/bpython/include/BPY_extern.h b/source/blender/bpython/include/BPY_extern.h new file mode 100644 index 00000000000..8aa9a2502fc --- /dev/null +++ b/source/blender/bpython/include/BPY_extern.h @@ -0,0 +1,60 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +struct Text; +struct ID; +struct ScriptLink; +struct ListBase; +struct SpaceText; +struct _object; // forward declaration for PyObject ! + + +void BPY_start_python(void); +void BPY_end_python(void); +int BPY_Err_getLinenumber(void); +const char *BPY_Err_getFilename(void); +void BPY_Err_Handle(struct Text *text); +struct _object *BPY_txt_do_python(struct SpaceText* st); +void BPY_free_compiled_text(struct Text* text); +void BPY_clear_bad_scriptlink(struct ID *id, struct Text *byebye); +void BPY_clear_bad_scriptlinks(struct Text *byebye); +void BPY_clear_bad_scriptlist(struct ListBase *, struct Text *byebye); +void BPY_do_all_scripts(short event); +void BPY_do_pyscript(struct ID *id, short event); +void BPY_free_scriptlink(struct ScriptLink *slink); +void BPY_copy_scriptlink(struct ScriptLink *scriptlink); + +/* format importer hook */ +int BPY_call_importloader(char *name); + +int BPY_spacetext_is_pywin(struct SpaceText *st); +void BPY_spacetext_do_pywin_draw(struct SpaceText *st); +void BPY_spacetext_do_pywin_event(struct SpaceText *st, unsigned short event, short val); diff --git a/source/blender/bpython/include/BPY_objtypes.h b/source/blender/bpython/include/BPY_objtypes.h new file mode 100644 index 00000000000..91cdc5ceb96 --- /dev/null +++ b/source/blender/bpython/include/BPY_objtypes.h @@ -0,0 +1,38 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_mesh_types.h" +#include "DNA_curve_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" + diff --git a/source/blender/bpython/intern/BPY_constobject.c b/source/blender/bpython/intern/BPY_constobject.c new file mode 100644 index 00000000000..9f1a6b4cc3b --- /dev/null +++ b/source/blender/bpython/intern/BPY_constobject.c @@ -0,0 +1,183 @@ +/* + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +$Id$ + +This is code to emulate a readonly Dictionary/Class object +for storage of Constants + +Inserting readonly values: + +PyObject *constants = ConstObject_New(); +insertConst(constants, "item", PyInt_FromInt(CONSTANT)); +... + + +Constant values are accessed in python by either: + +c = module.Const.CONSTANT + + or + +c = module.Const['CONSTANT'] + +*/ + +#include "Python.h" +#include "BPY_macros.h" + +#include "BPY_constobject.h" + +#define Const_Check(v) ((v)->ob_type == &Const_Type) + + +/* ----------------------------------------------------- */ +/* Declarations for objects of type const */ + + +PyTypeObject Const_Type; + +/* PROTOS */ + + + +static constobject * +newconstobject() +{ + constobject *self; + Const_Type.ob_type = &PyType_Type; + self = PyObject_NEW(constobject, &Const_Type); + if (self == NULL) + return NULL; + self->dict = PyDict_New(); + return self; +} + +char ConstObject_doc[] = "Readonly dictionary type\n\n\ +This is used as a container for constants, which can be accessed by two ways:\n\ +\n\ + c = <ConstObject>.<attribute>\n\ +\n\ +or\n\ + c = <ConstObject>['<attribute>']"; + +PyObject *ConstObject_New(void) +{ + return (PyObject *) newconstobject(); +} + +PyObject *const_repr(constobject *self) +{ + PyObject *repr; + repr = PyObject_Repr(self->dict); + return repr; +} + +static void const_dealloc(PyObject *self) { + Py_DECREF(((constobject *)self)->dict); + PyMem_DEL(self); +} +static PyObject * +const_getattr(constobject *self, char *name) +{ + PyObject *item; + if (STREQ(name, "__doc__")) { + return PyString_FromString(ConstObject_doc); + } + if (STREQ(name, "__members__")) { + return PyDict_Keys(self->dict); + } + item = PyDict_GetItemString(self->dict, name); /* borrowed ref ! */ + if (item) + Py_INCREF(item); + if (!item) { + PyErr_SetString(PyExc_AttributeError, name); + } + return item; +} + +/* inserts a constant with name into the dictionary self */ +void insertConst(PyObject *self, char *name, PyObject *cnst) +{ + PyDict_SetItemString(((constobject *)self)->dict, name, cnst); +} + + +/* Code to access const objects as mappings */ + +static int +const_length(constobject *self) +{ + return 0; +} + +static PyObject * +const_subscript(constobject *self, PyObject *key) +{ + PyObject *item; + item = PyDict_GetItem(self->dict, key); + if (item) + Py_INCREF(item); + return item; +} + +static int +const_ass_sub(constobject *self, PyObject *v, PyObject *w) +{ + /* no write access */ + return 0; +} + +static PyMappingMethods const_as_mapping = { + (inquiry)const_length, /*mp_length*/ + (binaryfunc)const_subscript, /*mp_subscript*/ + (objobjargproc)const_ass_sub, /*mp_ass_subscript*/ +}; + +/* -------------------------------------------------------- */ + +PyTypeObject Const_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "const", /*tp_name*/ + sizeof(constobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) const_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) const_getattr, /*tp_getattr*/ + (setattrfunc) 0, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) const_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + &const_as_mapping, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + diff --git a/source/blender/bpython/intern/BPY_constobject.h b/source/blender/bpython/intern/BPY_constobject.h new file mode 100644 index 00000000000..b75ba202765 --- /dev/null +++ b/source/blender/bpython/intern/BPY_constobject.h @@ -0,0 +1,40 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +typedef struct { + PyObject_HEAD + PyObject *dict; + +} constobject; + +PyObject *ConstObject_New(void); +void insertConst(PyObject *self, char *name, PyObject *cnst); + diff --git a/source/blender/bpython/intern/BPY_csg.c b/source/blender/bpython/intern/BPY_csg.c new file mode 100644 index 00000000000..7237a843428 --- /dev/null +++ b/source/blender/bpython/intern/BPY_csg.c @@ -0,0 +1,239 @@ + +/** CSG wrapper module + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * $Id$ + */ + +// TODO + + +#include "Python.h" + +#include "BPY_csg.h" + +#include "BKE_booleanops_mesh.h" +#include "BKE_booleanops.h" +#include "MEM_guardedalloc.h" + +#include "b_interface.h" + +#ifdef DEBUG + #define CSG_DEBUG(str) \ + { printf str; } +#else + #define CSG_DEBUG(str) \ + {} +#endif + + +/////////////////////////////////////////////////////////////// +// CSG python object struct + + +typedef struct _CSGMesh { + PyObject_VAR_HEAD + CSG_MeshDescriptor *imesh; +} PyCSGMesh; + +// PROTOS + +static PyObject *newPyCSGMesh(CSG_MeshDescriptor *imesh); + +static void CSGMesh_dealloc(PyObject *self); +static PyObject *CSGMesh_getattr(PyObject *self, char *attr); + + +static char CSGMesh_Type_doc[] = "CSG mesh type"; + +static PyTypeObject PyCSGMesh_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "CSGMesh", /*tp_name*/ + sizeof(PyCSGMesh), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) CSGMesh_dealloc, /*tp_dealloc*/ + (printfunc)0, /*tp_print*/ + (getattrfunc)CSGMesh_getattr, /*tp_getattr*/ + (setattrfunc)0, /*tp_setattr*/ + (cmpfunc)0, /*tp_compare*/ + (reprfunc)0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc)0, /*tp_hash*/ + (ternaryfunc)0, /*tp_call*/ + (reprfunc)0, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + CSGMesh_Type_doc /* Documentation string */ +}; + +/////////////////////////////////////////////////////////////// +// CSG object methods + + +static PyObject *CSGMesh_add(PyObject *self, PyObject *args) +{ + CSG_MeshDescriptor *new_imesh = + (CSG_MeshDescriptor *) MEM_mallocN(sizeof(CSG_MeshDescriptor), + "CSG_IMesh"); + + PyCSGMesh *c2; + int success = 0; + + PyCSGMesh *c1 = (PyCSGMesh *) self; + if (!PyArg_ParseTuple(args, "O!", &PyCSGMesh_Type, &c2)) return NULL; + + success = CSG_PerformOp(c1->imesh, c2->imesh, 2, new_imesh); + + if (!success) { + PyErr_SetString(PyExc_RuntimeError, "Sorry. Didn't work"); + return NULL; // exception + } + return newPyCSGMesh(new_imesh); +} + + +static PyMethodDef CSGMesh_methods[] = { + {"union", CSGMesh_add, METH_VARARGS, 0 }, + // add more methods here + {NULL, NULL, 0, NULL} +}; + + +static void CSGMesh_dealloc(PyObject *self) +{ + CSG_MeshDescriptor *imesh = ((PyCSGMesh *) self)->imesh; + CSG_DEBUG(("object was destroyed\n")); + // TODO: delete (free) struct ptr + CSG_DestroyMeshDescriptor(imesh); + MEM_freeN(imesh); + PyMem_DEL(self); +} + +static PyObject *CSGMesh_getattr(PyObject *self, char *attr) +{ + return Py_FindMethod(CSGMesh_methods, (PyObject *) self, attr); +} +/////////////////////////////////////////////////////////////// +// CSG module methods + +static PyObject *newPyCSGMesh(CSG_MeshDescriptor *imesh) +{ + PyCSGMesh *c = PyObject_NEW(PyCSGMesh, &PyCSGMesh_Type); + CSG_DEBUG(("object was created\n")); + c->imesh = imesh; + // add init bla here + return (PyObject *) c; +} + +static PyObject *CSGmodule_CSGMesh(PyObject *self, PyObject *args) +{ + char *name; + + Object *obj; + CSG_MeshDescriptor *new_imesh; + + if (!PyArg_ParseTuple(args, "s", &name)) return NULL; + new_imesh = (CSG_MeshDescriptor *) MEM_mallocN( + sizeof(CSG_MeshDescriptor), + "CSG_IMesh"); + + // get object by name, return its mesh data + // and do the conversion + // CSG_LoadBlenderMesh(name, new_imesh); + + obj = (Object *) getFromList(getObjectList(), name); + + if (!obj) { + PyErr_SetString(PyExc_AttributeError, + "requested Object does not exist"); + return NULL; + } + + if (obj->type != OB_MESH) { + PyErr_SetString(PyExc_TypeError, "Mesh object expected"); + return NULL; + } + + if (!CSG_LoadBlenderMesh(obj, new_imesh)) { + PyErr_SetString(PyExc_RuntimeError, + "FATAL: Could not acquire mesh data"); + return NULL; + } + return newPyCSGMesh(new_imesh); +} + +static PyObject *CSGmodule_toBlenderMeshObject(PyObject *self, + PyObject *args) +{ + Object *new_object; + PyCSGMesh *pmesh; + CSG_MeshDescriptor *c; + + float identity[4][4] = { {1.0, 0.0, 0.0, 0.0}, + {0.0, 1.0, 0.0, 0.0}, + {0.0, 0.0, 1.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}; + + + if (!PyArg_ParseTuple(args, "O!", &PyCSGMesh_Type, &pmesh)) return NULL; + c = pmesh->imesh; + new_object = object_new(OB_MESH); + + if (!PyArg_ParseTuple(self, "")) return NULL; + // TODO: blender mesh conversion + ConvertCSGDescriptorsToMeshObject(new_object, &c->m_descriptor, + &c->m_face_iterator, + &c->m_vertex_iterator, + identity); + + // return resulting object + return DataBlock_fromData(new_object); +} + +static PyMethodDef CSGmodule_methods[] = { + {"CSGMesh", CSGmodule_CSGMesh , METH_VARARGS, 0 }, + {"toObject", CSGmodule_toBlenderMeshObject, METH_VARARGS, 0 }, + {NULL, NULL, 0, NULL} +}; + +// MODULE INITIALIZATION + +void initcsg() +{ + PyObject *mod; + PyCSGMesh_Type.ob_type = &PyType_Type; + mod = Py_InitModule("csg", CSGmodule_methods); + +} + diff --git a/source/blender/bpython/intern/BPY_csg.h b/source/blender/bpython/intern/BPY_csg.h new file mode 100644 index 00000000000..8b4a829a057 --- /dev/null +++ b/source/blender/bpython/intern/BPY_csg.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include "BPY_macros.h" + +#include "opy_datablock.h" +#include "b_interface.h" diff --git a/source/blender/bpython/intern/BPY_image.c b/source/blender/bpython/intern/BPY_image.c new file mode 100644 index 00000000000..a94abb594a7 --- /dev/null +++ b/source/blender/bpython/intern/BPY_image.c @@ -0,0 +1,103 @@ +/** + * Image Datablocks + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "opy_datablock.h" + +#include "DNA_image_types.h" +#include "BKE_image.h" + +#include "BPY_macros.h" +#include "b_interface.h" + +PyObject *INITMODULE(Image)(void); + +/* Image_Get */ +DATABLOCK_GET(Imagemodule, image, getImageList()) + +char Imagemodule_load_doc[] = "(filename) - return image from file 'filename' as Image object"; + +PyObject *Imagemodule_load(PyObject *self, PyObject *args) +{ + char *name; + Image *im; + + if (!PyArg_ParseTuple(args, "s", &name)) { + PyErr_SetString(PyExc_TypeError, "filename expected"); + return 0; + } + + im = add_image(name); + if (im) { + return DataBlock_fromData(im); + } else { + PyErr_SetString(PyExc_IOError, "couldn't load image"); + return 0; + } +} + +DataBlockProperty Image_Properties[]= { + {"xrep", "xrep", DBP_TYPE_SHO, 0, 1.0, 16.0}, + {"yrep", "yrep", DBP_TYPE_SHO, 0, 1.0, 16.0}, +// {"PackedFile", "*packedfile", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + {NULL} +}; + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Imagemodule) + +struct PyMethodDef Imagemodule_methods[] = { + MethodDef(get), + MethodDef(load), + // for compatibility: + {"Load", Imagemodule_load, METH_VARARGS, Imagemodule_load_doc}, + {NULL, NULL} +}; + + +/* +void Image_getattr(void *vdata, char *name) +{ +} +*/ + + +PyObject *INITMODULE(Image)(void) +{ + PyObject *mod= Py_InitModule(SUBMODULE(Image), Imagemodule_methods); + return mod; +} + + + + diff --git a/source/blender/bpython/intern/BPY_ipo.c b/source/blender/bpython/intern/BPY_ipo.c new file mode 100644 index 00000000000..237692ca38d --- /dev/null +++ b/source/blender/bpython/intern/BPY_ipo.c @@ -0,0 +1,717 @@ +/** Ipo module; access to Ipo datablocks in Blender + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ +#include "MEM_guardedalloc.h" + +#include "Python.h" +#include "BPY_macros.h" +#include "BPY_tools.h" + +#include "b_interface.h" // most datatypes + +#include "opy_datablock.h" + +#include "DNA_curve_types.h" + +#include "BSE_editipo.h" + +/* GLOBALS */ + +/* These should be put into a proper dictionary for quicker retrieval..*/ + +NamedEnum g_OB_ipocodes[] = { + + { "LocX", OB_LOC_X }, + { "LocY", OB_LOC_Y }, + { "LocZ", OB_LOC_Z }, + { "dLocX", OB_DLOC_X }, + { "dLocY", OB_DLOC_Y }, + { "dLocZ", OB_DLOC_Z }, + { "RotX", OB_ROT_X }, + { "RotY", OB_ROT_Y }, + { "RotZ", OB_ROT_Z }, + { "dRotX", OB_DROT_X }, + { "dRotY", OB_DROT_Y }, + { "dRotZ", OB_DROT_Z }, + { "SizeX", OB_SIZE_X }, + { "SizeY", OB_SIZE_Y }, + { "SizeY", OB_SIZE_Z }, + { "dSizeX", OB_DSIZE_X }, + { "dSizeY", OB_DSIZE_Y }, + { "dSizeY", OB_DSIZE_Z }, + { "Layer", OB_LAY }, + { "Time", OB_TIME }, + { 0, 0 } +}; + +NamedEnum g_MA_ipocodes[] = { + + { "R", MA_COL_R }, + { "G", MA_COL_G }, + { "B", MA_COL_B }, + { "Alpha", MA_ALPHA}, + { "SpecR", MA_SPEC_R }, + { "SpecG", MA_SPEC_G }, + { "SpecB", MA_SPEC_B }, + { "MirR", MA_MIR_R }, + { "MirG", MA_MIR_G }, + { "MirB", MA_MIR_B }, + { "Emit", MA_EMIT }, + { "Amb", MA_AMB }, + { "Spec", MA_SPEC }, + { "Hard", MA_HARD }, + { "SpTra", MA_SPTR }, + { "Ang", MA_ANG }, + { "HaSize", MA_HASIZE }, + { 0, 0 } +}; + +NamedEnum g_WO_ipocodes[] = { + { "HorR", WO_HOR_R }, + { "HorG", WO_HOR_G }, + { "HorB", WO_HOR_B }, + { "ZenR", WO_ZEN_R }, + { "ZenG", WO_ZEN_G }, + { "ZenB", WO_ZEN_B }, + { "Expos", WO_EXPOS }, + { "Misi", WO_MISI }, + { "MisDi", WO_MISTDI }, + { "MisSta", WO_MISTSTA }, + { "MisHi", WO_MISTHI }, + { "StarR", WO_STAR_R }, + { "StarG", WO_STAR_G }, + { "StarB", WO_STAR_B }, + { "StarDi", WO_STARDIST }, + { "StarSi", WO_STARSIZE }, + { 0, 0 } +}; + +NamedEnum g_CA_ipocodes[] = { + { "Lens", CAM_LENS }, + { "ClSta", CAM_STA }, + { "ClEnd", CAM_END }, + { 0, 0 } +}; + +PyObject *g_ipoBlockTypes; // global for ipo type container +PyObject *g_interpolationTypes; // global for interpolation type container +PyObject *g_extrapolationTypes; // global for extrapolation type container + +typedef struct _PyBezTriple { + PyObject_VAR_HEAD + + BezTriple bzt; +} PyBezTriple; + + +void pybzt_dealloc(PyObject *self) { + PyMem_DEL(self); +} + +PyObject *pybzt_repr(PyObject *self) { + return PyString_FromString("[BezTriple]"); +} + +/* XXX */ + +NamedEnum bez_triple_flags[]= { + {"Free", HD_FREE}, + {"Auto", HD_AUTO}, + {"Vect", HD_VECT}, + {"Align", HD_ALIGN}, + {NULL} +}; + +DataBlockProperty BezTriple_Properties[]= { + {"h1", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {0,0}, {3,3,-sizeof(float)}}, + {"pt", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {1,0}, {3,3,-sizeof(float)}}, + {"h2", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {2,0}, {3,3,-sizeof(float)}}, + + {"f1", "f1", DBP_TYPE_CHA, 0, 0.0, 1.0}, + {"f2", "f2", DBP_TYPE_CHA, 0, 0.0, 1.0}, + {"f3", "f3", DBP_TYPE_CHA, 0, 0.0, 1.0}, + + {"h1Type", "h1", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, + {"h2Type", "h2", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, + + {"h1t", "h1", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, + {"h2t", "h2", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, + + {NULL} +}; + +PyObject *pybzt_getattr(PyObject *self, char *name) { + PyBezTriple *pybzt= (PyBezTriple *) self; + + return datablock_getattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt); +} + +int pybzt_setattr(PyObject *self, char *name, PyObject *ob) { + PyBezTriple *pybzt= (PyBezTriple *) self; + + return datablock_setattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt, ob); +} + +PyTypeObject PyBezTriple_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "BezTriple", /*tp_name*/ + sizeof(PyBezTriple), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) pybzt_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) pybzt_getattr, /*tp_getattr*/ + (setattrfunc) pybzt_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) pybzt_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + +static char pybzt_create_doc[]= "() - Create a new BezTriple object"; +PyObject *pybzt_create(PyObject *self, PyObject *args) { + PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type); + // BezTriple *bzt= &py_bzt->bzt; + + BPY_TRY(PyArg_ParseTuple(args, "")); + + memset(&py_bzt->bzt,0,sizeof(py_bzt->bzt)); + + return (PyObject *) py_bzt; +} + +PyObject *pybzt_from_bzt(BezTriple *bzt) { + PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type); + + memcpy(&py_bzt->bzt, bzt, sizeof(*bzt)); + + return (PyObject *) py_bzt; +} + + +typedef struct _PyIpoCurve { + PyObject_VAR_HEAD + + IpoCurve *icu; +} PyIpoCurve; + + +/********************/ +/* IpoCurve methods */ + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, IpoCurve) + +#define DICT_FROM_CONSTDICT(x) \ + ((constobject *) x)->dict + +/** sets an enum int value 'by name' from the dictionary dict */ + +static PyObject *setEnum_fromDict(short *i, PyObject *dict, char *key, char *errmsg) +{ + PyObject *p; + p = PyDict_GetItemString(dict, key); + if (!p) { + PyErr_SetString(PyExc_TypeError, errmsg); + return NULL; + } + + *i = (short) PyInt_AsLong(p); + return BPY_incr_ret(Py_None); +} + +static char IpoCurve_setInterpolation_doc[] = +"(type) - Set interpolation to one of: ['Constant', 'Linear', 'Bezier']"; + +static PyObject *IpoCurve_setInterpolation(PyObject *self, PyObject *args) +{ + char *typename; + IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu; + + BPY_TRY(PyArg_ParseTuple(args, "s", &typename)); + + return setEnum_fromDict(&ipocurve->ipo, DICT_FROM_CONSTDICT(g_interpolationTypes), + typename, "Improper interpolation type, see Ipo.InterpolationTypes"); + +} + +static char IpoCurve_setExtrapolation_doc[] = +"(type) - Set interpolation to one of: ['Constant', 'Linear', 'Cyclic', 'CyclicLinear']"; + +static PyObject *IpoCurve_setExtrapolation(PyObject *self, PyObject *args) +{ + char *typename; + IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu; + + BPY_TRY(PyArg_ParseTuple(args, "s", &typename)); + + + return setEnum_fromDict(&ipocurve->extrap, DICT_FROM_CONSTDICT(g_extrapolationTypes), + typename, "Improper extrapolation type, see Ipo.ExtrapolationTypes"); +} + +static char IpoCurve_getInterpolation_doc[] = +"() - Returns interpolation type"; + +static PyObject *IpoCurve_getInterpolation(PyObject *self, PyObject *args) +{ + IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu; + + switch (ipocurve->ipo) { + case IPO_CONST: return PyString_FromString("Constant"); + case IPO_LIN: return PyString_FromString("Linear"); + case IPO_BEZ: return PyString_FromString("Bezier"); + default: return PyString_FromString("<not defined>"); + } +} + +static char IpoCurve_getExtrapolation_doc[] = +"() - Returns extrapolation type"; + +static PyObject *IpoCurve_getExtrapolation(PyObject *self, PyObject *args) +{ + IpoCurve *ipocurve = (IpoCurve *) ((PyIpoCurve *) self)->icu; + + switch (ipocurve->extrap) { + case IPO_HORIZ: return PyString_FromString("Constant"); + case IPO_DIR: return PyString_FromString("Linear"); + case IPO_CYCL: return PyString_FromString("Cyclic"); + case IPO_CYCLX: return PyString_FromString("CyclicLinear"); + default: return PyString_FromString("<not defined>"); + } + +} + +static char IpoCurve_eval_doc[] = +"(time = <current frame>) - evaluates ipo at time 'time' and returns result\n\ +(float). If 'time' is not specified, the current frame value is taken"; + +static PyObject *IpoCurve_eval(PyObject *self, PyObject *args) +{ + PyIpoCurve *pIpocurve = (PyIpoCurve *) self; + float time = CurrentFrame; + + BPY_TRY(PyArg_ParseTuple(args, "|f", &time)); + + return PyFloat_FromDouble(eval_icu(pIpocurve->icu, time)); +} + +static char IpoCurve_update_doc[] = +"() - update and recalculate IpoCurve"; + +static PyObject *IpoCurve_update(PyObject *self, PyObject *args) +{ + + BPY_TRY(PyArg_ParseTuple(args, "")); + + testhandles_ipocurve(((PyIpoCurve *) self)->icu); // recalculate IPO + + Py_INCREF(Py_None); + return Py_None; +} + +static struct PyMethodDef IpoCurve_methods[] = { + MethodDef(setInterpolation), + MethodDef(getInterpolation), + MethodDef(setExtrapolation), + MethodDef(getExtrapolation), + MethodDef(eval), + MethodDef(update), + {NULL, NULL} +}; + + +PyObject *IpoCurve_getattr(PyObject *self, char *name) { + PyIpoCurve *py_icu= (PyIpoCurve *) self; + IpoCurve *icu= py_icu->icu; + + if (STREQ(name, "type")) { + return IpoCurve_getInterpolation(self, Py_BuildValue("")); + } else if (STREQ(name, "extend")) { + return IpoCurve_getExtrapolation(self, Py_BuildValue("")); + } else if (STREQ(name, "name")) { + char icu_name[32]= ""; + + switch (icu->blocktype) { + case ID_OB: + getname_ob_ei(icu->adrcode, icu_name, 0); + break; + case ID_MA: + getname_mat_ei(icu->adrcode, icu_name); + break; + case ID_WO: + getname_world_ei(icu->adrcode, icu_name); + break; + case ID_SEQ: + getname_seq_ei(icu->adrcode, icu_name); + break; + case ID_CU: + getname_cu_ei(icu->adrcode, icu_name); + break; + case ID_KE: + getname_key_ei(icu->adrcode, icu_name); + break; + case ID_LA: + getname_la_ei(icu->adrcode, icu_name); + break; + case ID_CA: + getname_cam_ei(icu->adrcode, icu_name); + break; + default: + return PyString_FromString("<unknown>"); + } + + return PyString_FromString(icu_name); + } else if (STREQ(name, "points")) { + PyObject *list= PyList_New(icu->totvert); + BezTriple *bzt= icu->bezt; + int i; + + for (i=0; i<icu->totvert; i++) { + PyList_SetItem(list, i, pybzt_from_bzt(bzt)); + bzt++; + } + + return list; + } + return Py_FindMethod(IpoCurve_methods, (PyObject*)self, name); +} + +int IpoCurve_setattr(PyObject *self, char *name, PyObject *ob) { + PyIpoCurve *py_icu= (PyIpoCurve *) self; + IpoCurve *icu= py_icu->icu; + + if (STREQ(name, "points")) { + int i, len; + BezTriple *bzt; + + if (!PySequence_Check(ob) || !BPY_check_sequence_consistency(ob, &PyBezTriple_Type)) + return py_err_ret_int(PyExc_AttributeError, "Expected list of BezTriples"); + + len= PySequence_Length(ob); + + if (icu->bezt) // free existing (IF) + MEM_freeN(icu->bezt); + + icu->totvert= len; + if (len) icu->bezt= MEM_mallocN(len*sizeof(BezTriple), "beztriples"); + + bzt= icu->bezt; + for (i=0; i<len; i++) { + PyBezTriple *pybzt= (PyBezTriple*) PySequence_GetItem(ob, i); + + memcpy(bzt, &pybzt->bzt, sizeof(BezTriple)); + bzt++; + + Py_DECREF(pybzt); + } + + /* Twice for auto handles */ + calchandles_ipocurve(icu); + calchandles_ipocurve(icu); + + boundbox_ipocurve(icu); + sort_time_ipocurve(icu); + + return 0; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + +void IpoCurve_dealloc(PyObject *self) { + PyMem_DEL(self); +} + +PyObject *IpoCurve_repr(PyObject *self) { + char s[256]; + sprintf (s, "[IpoCurve %.32s]", + PyString_AsString(IpoCurve_getattr(self, "name"))); + return Py_BuildValue("s", s); +} + +PyTypeObject PyIpoCurve_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "IpoCurve", /*tp_name*/ + sizeof(PyIpoCurve), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) IpoCurve_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) IpoCurve_getattr, /*tp_getattr*/ + (setattrfunc) IpoCurve_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) IpoCurve_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + +PyObject *IpoCurve_from_icu(IpoCurve *icu) { + PyIpoCurve *ob= PyObject_NEW(PyIpoCurve, &PyIpoCurve_Type); + + ob->icu= icu; + + return (PyObject *) ob; +} + +PyObject *make_icu_list (ListBase *curves) { + ListBase lb= *curves; + IpoCurve *icu= (IpoCurve *) lb.first; + PyObject *list= PyList_New(0); + PyObject *pyipo; + + while (icu) { + pyipo = IpoCurve_from_icu(icu); + PyList_Append(list, pyipo); + Py_DECREF(pyipo); + icu= icu->next; + } + + return list; +} + +DataBlockProperty Ipo_Properties[]= { + {"curves", "curve", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, make_icu_list}, + {NULL} +}; + + +/**********************/ +/* Ipo module methods */ + +DATABLOCK_GET(Ipomodule, ipo, getIpoList()) + +static char Ipomodule_New_doc[] = +"(type, name = <default>) - Creates a new Ipo block of the specified type,\n\ +which must be of the appropriate datablock ID type (e.g. ID_OB, ID_MA, ...)"; + + +static PyObject *Ipomodule_New(PyObject *self, PyObject *args) +{ + Ipo *ipo; + int type; + PyObject *p; + char *name = NULL, *typename; + + BPY_TRY(PyArg_ParseTuple(args, "s|s", &typename, &name)); + p = PyDict_GetItemString(((constobject *)g_ipoBlockTypes)->dict, typename); + if (!p) { + PyErr_SetString(PyExc_TypeError, "Improper Ipo type, see Ipo.Types"); + return NULL; + } + + type = PyInt_AsLong(p); + + if (!name) { + switch(type) { + case ID_OB: name = "Objpo"; break; + case ID_MA: name = "MatIpo"; break; + case ID_SEQ: name = "SeqIpo"; break; + case ID_CU: name = "CurveIpo"; break; + case ID_KE: name = "KeyIpo"; break; + case ID_WO: name = "WorldIpo"; break; + case ID_LA: name = "LampIpo"; break; + case ID_CA: name = "CamIpo"; break; + case ID_SO: name = "SndIpo"; break; + case ID_AC: name = "ActionIpo"; break; + default: + PyErr_SetString(PyExc_TypeError, "Internal error, illegal type"); + return NULL; + } + } + + ipo = ipo_new(type, name); + return DataBlock_fromData(ipo); +} + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Ipomodule) +struct PyMethodDef Ipomodule_methods[] = { + + MethodDef(New), + MethodDef(get), + {"BezTriple", pybzt_create, METH_VARARGS, pybzt_create_doc}, + + {NULL, NULL} +}; + +/********************/ +/* Ipoblock methods */ + +/* slow and inefficient lookup function , use proper dictionaries in future */ +short code_lookup(NamedEnum *codetab, char *name) +{ + int i = 0; + + while(codetab[i].name) + { + if (!strcmp(codetab[i].name, name)) + return codetab[i].num; + i++; + } + return -1; +} + +static char Ipo_addCurve_doc[]= +"(type, curve = None) - adds IpoCurve 'curve' to the IpoBlock under type id 'type'"; +PyObject *Ipo_addCurve(PyObject *self, PyObject *args) +{ + + Ipo *ipo = (Ipo *) ((DataBlock *) self)->data; + NamedEnum *lookup; + + short code; + + char *type; + PyIpoCurve *curve = NULL; + IpoCurve *ipocurve, *existingIpoCurve; + + BPY_TRY(PyArg_ParseTuple(args, "s|O!", &type, &PyIpoCurve_Type, &curve)); + + switch (ipo->blocktype) { + case ID_OB: + lookup = g_OB_ipocodes; + break; + case ID_CA: + lookup = g_CA_ipocodes; + break; + case ID_MA: + lookup = g_MA_ipocodes; + break; + case ID_WO: + lookup = g_WO_ipocodes; + break; + default: + PyErr_SetString(PyExc_TypeError, "Ipo type not (YET) supported"); + return NULL; + } + code = code_lookup(lookup, type); + if (code == -1) { + PyErr_SetString(PyExc_TypeError, "Unknown IpoCurve type"); + return NULL; + } + + if (!curve) { + ipocurve = ipocurve_new(); // malloc new ipocurve + } else { // add existing curve: + ipocurve = ipocurve_copy(curve->icu); // copy ipocurve + } + + ipocurve->adrcode = code; // re-code ipo + ipocurve->blocktype = ipo->blocktype; + + existingIpoCurve = ipo_findcurve(ipo, code); + if (existingIpoCurve) { + BLI_remlink(&(ipo->curve), existingIpoCurve); // remove existing + MEM_freeN(existingIpoCurve); + } + BLI_addtail(&(ipo->curve), ipocurve); // add curve to list + return IpoCurve_from_icu(ipocurve); +} + +static char Ipo_update_doc[]= +"() - Recalculate the ipo and update linked objects"; + +PyObject *Ipo_update(PyObject *self, PyObject *args) { + DataBlock *ipoblock = (DataBlock *) self; + Key *key; + + do_ipo((Ipo *) ipoblock->data); + + /* here we should signal all objects with keys that the ipo changed */ + + key= getKeyList()->first; + while(key) { + if(key->ipo == (Ipo *)ipoblock->data) do_spec_key(key); + key= key->id.next; + } + + return BPY_incr_ret(Py_None); +} + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Ipo) +struct PyMethodDef Ipo_methods[] = { + MethodDef(addCurve), + MethodDef(update), + {NULL, NULL} +}; + + +PyObject *initIpo(void) +{ + PyObject *mod, *dict, *d; + + mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Ipo", Ipomodule_methods); + dict = PyModule_GetDict(mod); + + // ipo block types + d = ConstObject_New(); + PyDict_SetItemString(dict, "Types", d); + g_ipoBlockTypes = d; + + insertConst(d, "Object", PyInt_FromLong(ID_OB)); + insertConst(d, "Material", PyInt_FromLong(ID_MA)); + insertConst(d, "Sequence", PyInt_FromLong(ID_SEQ)); + insertConst(d, "Curve", PyInt_FromLong(ID_CU)); + insertConst(d, "Key", PyInt_FromLong(ID_KE)); + insertConst(d, "World", PyInt_FromLong(ID_WO)); + insertConst(d, "Lamp", PyInt_FromLong(ID_LA)); + insertConst(d, "Camera", PyInt_FromLong(ID_CA)); + insertConst(d, "Sound", PyInt_FromLong(ID_SO)); + insertConst(d, "Action", PyInt_FromLong(ID_AC)); + + // interpolation types: + d = ConstObject_New(); + g_interpolationTypes = d; + PyDict_SetItemString(dict, "InterpolationTypes", d); + insertConst(d, "Constant", PyInt_FromLong(IPO_CONST)); + insertConst(d, "Linear", PyInt_FromLong(IPO_LIN)); + insertConst(d, "Bezier", PyInt_FromLong(IPO_BEZ)); + + d = ConstObject_New(); + g_extrapolationTypes = d; + PyDict_SetItemString(dict, "ExtrapolationTypes", d); + insertConst(d, "Constant", PyInt_FromLong(IPO_HORIZ)); + insertConst(d, "Linear", PyInt_FromLong(IPO_DIR)); + insertConst(d, "Cyclic", PyInt_FromLong(IPO_CYCL)); + insertConst(d, "CyclicLinear", PyInt_FromLong(IPO_CYCLX)); + + return mod; +} diff --git a/source/blender/bpython/intern/BPY_links.c b/source/blender/bpython/intern/BPY_links.c new file mode 100644 index 00000000000..e3c6458ef82 --- /dev/null +++ b/source/blender/bpython/intern/BPY_links.c @@ -0,0 +1,96 @@ +/** Helper functions to handle links between Object types, + * Script links */ + +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "BPY_macros.h" +#include "b_interface.h" + +/* GLOBALS */ + +PyObject *g_blenderdict; + +/* PROTOS */ +char *event_to_name(short event); +void set_scriptlinks(ID *id, short event); + +#ifndef SHAREDMODULE +PyObject *DataBlock_fromData (void *data); + + +void set_scriptlinks(ID *id, short event) +{ + PyObject *link; + + if (!g_blenderdict) // not initialized yet; this can happen at first file load + { + return; + } + if (GET_ID_TYPE(id) == ID_SCE) { + Py_INCREF(Py_None); + link = Py_None; + } else { + link = DataBlock_fromData(id); + } + + if (!link) + { + printf ("Internal error, unable to create PyBlock for script link\n"); + printf ("This is a bug; please report to bugs@blender.nl"); + Py_INCREF(Py_False); + PyDict_SetItemString(g_blenderdict, "bylink", Py_False); + return; + } else { + Py_INCREF(Py_True); + PyDict_SetItemString(g_blenderdict, "bylink", Py_True); + } + + PyDict_SetItemString(g_blenderdict, "link", link); + PyDict_SetItemString(g_blenderdict, "event", Py_BuildValue("s", event_to_name(event))); +} + +/* this is just a hack-added function to release a script link reference. + * The scriptlink concept will be redone later */ + +void release_scriptlinks(ID *id) +{ + PyObject *link; + if (!g_blenderdict) return; // return if Blender module was not initialized + link = PyDict_GetItemString(g_blenderdict, "link"); + Py_DECREF(link); + Py_INCREF(Py_None); + PyDict_SetItemString(g_blenderdict, "link", Py_None); +} + +#endif diff --git a/source/blender/bpython/intern/BPY_listbase_macro.h b/source/blender/bpython/intern/BPY_listbase_macro.h new file mode 100644 index 00000000000..5c5047d22d8 --- /dev/null +++ b/source/blender/bpython/intern/BPY_listbase_macro.h @@ -0,0 +1,62 @@ +/** + $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + These are macros to create python lists from base lists. +*/ + + + +/** example: DEFFUNC_GETLIST(text) defines a method for getting a list + * of text blocks */ + +// Example: _GETLIST(name) -> get_namelist +#define _GETLIST(x) get_##x##list + +// Function definition: +// DEFFUNC_GETLIST_MAIN(name) -> get_namelist(PyObject *self, PyObject *args) +#define DEFFUNC_GETLIST_MAIN(x) \ + PyObject *_GETLIST(x)(PyObject *self, PyObject *args) \ + { \ + ID *id; \ + PyObject *list; \ + list = PyList_New(0); \ + id = G.main->##x##.first; \ + while (id) \ + { \ + PyList_Append(list, PyString_FromString(id->name+2)); \ + id = id->next; \ + } \ + return list; \ + } \ + +// call the above function +#define GETLISTFUNC(x) _GETLIST(x) +// Prototype for the above function +#define GETLISTPROTO(x) PyObject *_GETLIST(x)(PyObject *, PyObject *) diff --git a/source/blender/bpython/intern/BPY_macros.h b/source/blender/bpython/intern/BPY_macros.h new file mode 100644 index 00000000000..9f9bea4864a --- /dev/null +++ b/source/blender/bpython/intern/BPY_macros.h @@ -0,0 +1,268 @@ + +/* bpython library macros + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + + +/* Hint: use gcc -E file.c to see what these macros are expanded in */ + +#include "api.h" // temporary defines for API version + +#include "BPY_listbase_macro.h" +#include "BKE_utildefines.h" + +/* CONSTANTS */ + +#define IDNAME 24 +#define PATH_MAXCHAR 128 + +/* ALIASES */ + +#define BPY_TRY(x) {if((!(x))) return NULL;} +#define BPY_TRY_TYPEERROR(x, str) \ + { if(!(x)) { \ + PyErr_SetString(PyExc_TypeError, str); \ + return NULL; }\ + } + +#define BPY_ADDCONST(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name)) +#define CurrentFrame (getGlobal()->scene->r.cfra) +#define RETURN_INC(ob) {Py_INCREF(ob); return ob; } + +/* Blender object internal 'reference' (user) counting */ +/* 'x' must be of type (ID *) */ + +#ifdef DEBUG + + #define BOB_USERCOUNT(x) \ + (x)->us + #define BOB_DECUSER(x) \ + printf("BOB_DECUSER: %s\n", (x)->name); \ + (x)->us ? (x)->us--:printf("FATAL: 0--\n") + #define BOB_INCUSER(x) \ + printf("BOB_INCUSER: %s\n", (x)->name); \ + id_us_plus(x) + /* safe ref-inc/dec */ + #define BOB_XDECUSER(x) \ + if (x) { \ + printf("BOB_XDECUSER: %s\n", (x)->name); \ + ((x)->us ? (x)->us--:printf("FATAL: 0--\n")); \ + } + #define BOB_XINCUSER(x) \ + if (x) { \ + printf("BOB_XINCUSER: %s\n", (x)->name); \ + if (x) id_us_plus(x); \ + } +#else + + #define BOB_USERCOUNT(x) \ + (x)->us + #define BOB_DECUSER(x) \ + (x)->us ? (x)->us--:printf("FATAL: 0--\n") + #define BOB_INCUSER(x) \ + id_us_plus(x) + /* safe ref-inc/dec */ + #define BOB_XDECUSER(x) \ + if (x) ((x)->us ? (x)->us--:printf("FATAL: 0--\n")) + #define BOB_XINCUSER(x) \ + if (x) id_us_plus(x) + +#endif + +/* WARNINGS, Verbose */ + +#define BPY_CHECKFLAG(x) (getGlobal()->f & x) +#define BPY_DEBUGFLAG BPY_CHECKFLAG(G_DEBUG) +#define BPY_debug(a) if BPY_DEBUGFLAG {printf a; } +#define BPY_warn(a) {printf a; } + +/* BLENDER DATABLOCK ACCESS */ + +/* these are relicts... */ +#define GS(a) (*((short *)(a))) +#define STREQ(str, a) ( strcmp((str), (a))==0 ) + +/** This macro should be used to get the (short) id type of a ID datablock + * structure (Object, Mesh, etc.) + * Usage is dangerous, so use it only if you know what you're doing :-) + * Otherwise, use DataBlock_type() or associated functions (datablock.c) + */ + +#define GET_ID_TYPE(x) (GS((x)->name)) + +/* gets the datablock's ID pointer. be careful with its usage, + * - no typechecking done! */ +#define DATABLOCK_ID(x) ( (ID *) ((DataBlock *) x)->data) + +/** This defines the Get method plus documentation for use in a + * Method definition list. + * Example: + * + * DATABLOCK_GET(modulename, objectname, listbase.first) + * + * This function, called in Python by: + * + * modulename.Get(name) + * + * returns a Python DataBlock object for the Blender object with name + * 'name'. If 'name' omitted, a list of all the objects in the + * given list (a linked list of ID pointers) is returned + */ + + +#define DATABLOCK_GET(uname, docname, list) \ +static char uname##_get_doc[]= \ +"([name]) - Get " #docname "s from Blender\n" \ +"\n" \ +"[name] The name of the " #docname " to return\n" \ +"\n" \ +"Returns a list of all " #docname "s if name is not specified"; \ + \ +static PyObject* uname##_get (PyObject *self, PyObject *args) { \ + return py_find_from_list(list, args); \ +} + +/** This macro defines the creation of new Objects */ + +#define DATABLOCK_NEW( modprefix, type, callfunc) \ +static char modprefix##_New_doc[] = \ +"() - returns new " #type " object"; \ + \ +PyObject *modprefix##_New (PyObject *self, PyObject *args) \ +{ \ + type *obj; \ + char *name = #type; \ + BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); \ + obj = callfunc; \ + return DataBlock_fromData(obj); \ +} \ + +#define DATABLOCK_ASSIGN_IPO(type, prefix) \ +static char type##_assignIpo_doc[]= \ +"(ipo) - assigns Ipo to object of type " #type ; \ + \ +static PyObject *type##_assignIpo(PyObject *self, PyObject *args) \ +{ \ + DataBlock *ipoblock; \ + Ipo *ipo; \ + type *object = PYBLOCK_AS(type, self); \ + \ + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &ipoblock));\ + if (!DataBlock_isType(ipoblock, ID_IP)) { \ + PyErr_SetString(PyExc_TypeError, "expects Ipo object"); \ + return 0; \ + } \ + ipo = PYBLOCK_AS_IPO(ipoblock); \ + \ + if (ipo->blocktype != GET_ID_TYPE((ID *) object)) { \ + PyErr_SetString(PyExc_TypeError, \ + "Ipo type does not match object type"); \ + return 0; \ + } \ + prefix##_assignIpo(object, ipo); \ + \ + Py_INCREF(Py_None); \ + return Py_None; \ +} \ + \ +static char type##_clrIpo_doc[]= \ +"(ipo) - clears Ipo" ; \ + \ +static PyObject *type##_clrIpo(PyObject *self, PyObject *args) \ +{ \ + type *object = PYBLOCK_AS(type, self); \ + BPY_TRY(PyArg_ParseTuple(args, "")); \ + prefix##_assignIpo(object, 0); \ + Py_INCREF(Py_None); \ + return Py_None; \ +} + +/** Macro used to define the MethodDef macro which is used again for defining + * module or object methods in the Method table, see e.g. BPY_scene.c + * + * Usage: + + * _MethodDef(delete, Scene) expands to: + * + * {"delete", Scene_delete, METH_VARARGS, Scene_delete_doc} + */ +#define _MethodDef(func, prefix) \ + {#func, prefix##_##func, METH_VARARGS, prefix##_##func##_doc} + +/** Mark the datablock wrapper as invalid. See BPY_text.c for details */ +#define MARK_INVALID(datablock) \ + ((DataBlock *) datablock)->data = NULL + +/** Check whether datablock wrapper is valid */ +#define CHECK_VALIDDATA(x, msg) \ + if (!x) { \ + PyErr_SetString(PyExc_RuntimeError, msg); \ + return 0; \ + } \ + + +/* OBJECT ACCESS */ + +/** retrieves name from BPYobject */ +#define getName(x) ((x)->id.name+2) +#define getUsers(x) ((x)->id.us) +#define getIDName(x) ((x)->name+2) +#define getIDUsers(x) ((x)->us) + +#define object_getMaterials(object) (object)->mat + +/** rename object with name */ + +/* ListBase of active object in scene */ +#define FirstBase (getGlobal()->scene->base.first) +#define ActiveBase (getGlobal()->scene->basact) +#define ObjectfromBase(base) (base->object) +#define SelectedAndLayer(base) (((base)->flag & SELECT) && ((base)->lay & getGlobal()->vd->lay)) +/* Active object (bright pink) */ + +#define ActiveObject (ActiveBase ? ObjectfromBase(ActiveBase) : NULL) + +/* returns 1 if textureface tf is selected/active, else 0 */ +#define isSelectedFace(tf) (((tf).flag & TF_SELECT) ? 1 : 0 ) +#define isActiveFace(tf) (((tf).flag & TF_ACTIVE) ? 1 : 0 ) + +/* some conversion macros */ + +#define PYBLOCK_AS(x, y) (x *) ((DataBlock *) y)->data +#define PYBLOCK_AS_TEXT(x) PYBLOCK_AS(Text, x) +#define PYBLOCK_AS_MATERIAL(x) PYBLOCK_AS(Material, x) +#define PYBLOCK_AS_OBJECT(x) PYBLOCK_AS(Object, x) +#define PYBLOCK_AS_MESH(x) PYBLOCK_AS(Mesh, x) +#define PYBLOCK_AS_LAMP(x) PYBLOCK_AS(Lamp, x) +#define PYBLOCK_AS_IPO(x) PYBLOCK_AS(Ipo, x) +#define PYBLOCK_AS_DATA(x) PYBLOCK_AS(void, x) diff --git a/source/blender/bpython/intern/BPY_main.c b/source/blender/bpython/intern/BPY_main.c new file mode 100644 index 00000000000..17995476749 --- /dev/null +++ b/source/blender/bpython/intern/BPY_main.c @@ -0,0 +1,672 @@ +/** + * blenkernel/py_main.c + * (cleaned up somewhat nzc apr-2001) + + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +/* NOTE: all externally callable routines have the prefix BPY_ + -- see also ../include/BPY_extern.h */ + +#include "BPY_main.h" +#include "BPY_modules.h" +#include "BPY_macros.h" +#include "DNA_space_types.h" + +#include "b_interface.h" +#include "mydevice.h" +#include "import.h" + +/* PROTOS */ + +extern void init_frozenmodules(void); // frozen module library +extern void initmxTextTools(void); +extern void inittess(void); // tesselator module + +void init_ourImport(void); + + +/* GLOBALS */ + +PyObject* ErrorObject = NULL; +PyObject* callback = NULL; +PyObject* callbackArgs = NULL; +PyObject* blenderprogname = NULL; +ID* script_link_id = NULL; + +/*------------------------------------------------------------------------*/ +/* START PYTHON (from creator.c) */ + +void INITMODULE(BLENDERMODULE)(void); + +struct _inittab blendermodules[] = { +#ifndef SHAREDMODULE // Blender module can alternatively be compiled shared + #ifdef STATIC_TEXTTOOLS // see api.h + { "mxTextTools" , initmxTextTools }, + #endif + { MODNAME(BLENDERMODULE) , INITMODULE(BLENDERMODULE) }, +#endif +#ifdef NO_RELEASE + { "tess" , inittess }, // GLU tesselator wrapper module +#endif + { 0, 0} +}; + +/* hack to make sure, inittab is extended only first time */ + +static short g_is_extended = 0; + +/** (Re)initializes the Python Interpreter. + * This function should be only called if the Python interpreter + * was not yet initialized (check Py_IsInitialized() ) + */ + +static void initBPythonInterpreter(void) +{ + Py_Initialize(); + + init_ourImport(); /* our own import, later: security */ + if (!BPY_CHECKFLAG(G_NOFROZEN)) { + init_frozenmodules(); /* initialize frozen modules unless disabled */ + } + init_syspath(); +} + +/** This function initializes Blender Python. It should be called only + * once at start, which is currently not the case (GameEngine Python). + * Therefore, it contains some dirty workarounds. They will be thrown + * into the grachten once the different APIs are merged into something + * more consistent. + * + */ + +void BPY_start_python(void) +{ + Py_SetProgramName("blender"); + if (BPY_DEBUGFLAG) { + + Py_VerboseFlag = 1; + Py_DebugFlag = 1; + } else { +#ifndef EXPERIMENTAL + Py_FrozenFlag = 1; /* no warnings about non set PYTHONHOME */ + Py_NoSiteFlag = 1; /* disable auto site module import */ +#endif + } + + if (!g_is_extended) { + g_is_extended = 1; + PyImport_ExtendInittab(blendermodules); /* extend builtin module table */ + } + + initBPythonInterpreter(); +#ifdef NO_RELEASE + if (PyRun_SimpleString("import startup")) + { + BPY_warn(("init script not found, continuing anyway\n")); + PyErr_Clear(); + return; + } +#endif +} + +/** Ends the Python interpreter. This cleans up all global variables + * Blender-Python descriptor objects will (MUST!) decref on their + * raw blender objects, so this function should be called more or less + * immediately before garbage collection actions. + */ + +void BPY_end_python(void) +{ + Py_Finalize(); +} + +void BPY_free_compiled_text(Text* text) +{ + if (!text->compiled) return; + Py_DECREF((PyObject*) text->compiled); + text->compiled = NULL; +} + +void syspath_append(PyObject *dir) +{ + PyObject *m, *d; + PyObject *o; + + PyErr_Clear(); + m = PyImport_ImportModule("sys"); + d = PyModule_GetDict(m); + o = PyDict_GetItemString(d, "path"); + if (!PyList_Check(o)) { + return; + } + PyList_Append(o, dir); + if (PyErr_Occurred()) { + Py_FatalError("could not build sys.path"); + } + Py_DECREF(m); +} + +/* build blender specific system path for external modules */ + +void init_syspath(void) +{ + PyObject *path; + PyObject *m, *d; + PyObject *p; + char *c; + + + char execdir[PATH_MAXCHAR], *progname; + + int n; + + path = Py_BuildValue("s", bprogname); + + m = PyImport_ImportModule(MODNAME(BLENDERMODULE) ".sys"); + if (m) { + d = PyModule_GetDict(m); + PyDict_SetItemString(d, "progname", path); + Py_DECREF(m); + } else { + BPY_debug(("Warning: could not set Blender.sys.progname\n")); + } + + progname = BLI_last_slash(bprogname); /* looks for the last dir separator */ + + c = Py_GetPath(); /* get python system path */ + PySys_SetPath(c); /* initialize */ + + n = progname - bprogname; + if (n > 0) { + strncpy(execdir, bprogname, n); + execdir[n] = '\0'; + + p = Py_BuildValue("s", execdir); + syspath_append(p); /* append to module search path */ + + /* set Blender.sys.progname */ + } else { + BPY_debug(("Warning: could not determine argv[0] path\n")); + } + /* TODO look for the blender executable in the search path */ + BPY_debug(("append to syspath: %s\n", U.pythondir)); + if (U.pythondir) { + p = Py_BuildValue("s", U.pythondir); + syspath_append(p); /* append to module search path */ + } + BPY_debug(("append done\n")); +} + + +#define FILENAME_LENGTH 24 +typedef struct _ScriptError { + char filename[FILENAME_LENGTH]; + int lineno; +} ScriptError; + +ScriptError g_script_error; + +int BPY_Err_getLinenumber() +{ + return g_script_error.lineno; +} + +const char *BPY_Err_getFilename() +{ + return g_script_error.filename; +} + +/** Returns (PyString) filename from a traceback object */ + +PyObject *traceback_getFilename(PyObject *tb) +{ + PyObject *v; + + v = PyObject_GetAttrString(tb, "tb_frame"); Py_DECREF(v); + v = PyObject_GetAttrString(v, "f_code"); Py_DECREF(v); + v = PyObject_GetAttrString(v, "co_filename"); + return v; +} + +/** Blender Python error handler. This catches the error and stores + * filename and line number in a global + */ + +void BPY_Err_Handle(Text *text) +{ + PyObject *exception, *err, *tb, *v; + + PyErr_Fetch(&exception, &err, &tb); + + if (!exception && !tb) { + printf("FATAL: spurious exception\n"); + return; + } + + strcpy(g_script_error.filename, getName(text)); + + if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { + // no traceback available when SyntaxError + PyErr_Restore(exception, err, tb); // takes away reference! + PyErr_Print(); + v = PyObject_GetAttrString(err, "lineno"); + g_script_error.lineno = PyInt_AsLong(v); + Py_XDECREF(v); + return; + } else { + PyErr_NormalizeException(&exception, &err, &tb); + PyErr_Restore(exception, err, tb); // takes away reference! + PyErr_Print(); + tb = PySys_GetObject("last_traceback"); + Py_INCREF(tb); + +// check traceback objects and look for last traceback in the +// same text file. This is used to jump to the line of where the +// error occured. If the error occured in another text file or module, +// the last frame in the current file is adressed + + while (1) { + v = PyObject_GetAttrString(tb, "tb_next"); + if (v == Py_None || + strcmp(PyString_AsString(traceback_getFilename(v)), getName(text))) + break; + Py_DECREF(tb); + tb = v; + } + + v = PyObject_GetAttrString(tb, "tb_lineno"); + g_script_error.lineno = PyInt_AsLong(v); + Py_XDECREF(v); + v = traceback_getFilename(tb); + strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH); + Py_XDECREF(v); + Py_DECREF(tb); + } +} + +/** Runs a Python string in the global name space of the given dictionary + 'globaldict' */ + +static PyObject *newGlobalDictionary(void) +{ + PyObject *d = PyDict_New(); + PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); + PyDict_SetItemString(d, "__name__", PyString_FromString("__main__")); + return d; +} + +static void releaseGlobalDictionary(PyObject *d) +{ + BPY_debug(("--- CLEAR namespace\n")); + PyDict_Clear(d); + Py_DECREF(d); // release dictionary +} + +PyObject *BPY_runPython(Text *text, PyObject *globaldict) +{ + PyObject *ret; + char* buf = NULL; + + if (!text->compiled) + { + buf = txt_to_buf(text); + /* bah, what a filthy hack -- removed */ + /* strcat(buf, "\n"); */ + text->compiled = Py_CompileString(buf, getName(text), Py_file_input); + MEM_freeN(buf); + if (PyErr_Occurred()) + { + BPY_free_compiled_text(text); + return 0; + } + } + BPY_debug(("Run Python script \"%s\" ...\n", getName(text))); + ret = PyEval_EvalCode(text->compiled, globaldict, globaldict); + return ret; +} + +/** This function is executed whenever ALT+PKEY is pressed -> drawtext.c + It returns the global namespace dictionary of the script context + (which is created newly when CLEAR_NAMESPACE is defined). + This may be stored in the SpaceText instance to give control over + namespace persistence. Remember that the same script may be executed + in several windows.. + Namespace persistence is desired for scripts that use the GUI and + store callbacks to the current script. +*/ + +PyObject *BPY_txt_do_python(SpaceText *st) +{ + PyObject* d = NULL; + PyObject *ret; + Text *text = st->text; + + if (!text) + { + return NULL; + } + + /* TODO: make this an option: */ +#ifdef CLEAR_NAMESPACE + BPY_debug(("--- enable clear namespace\n")); + st->flags |= ST_CLEAR_NAMESPACE; +#endif + +#ifdef CLEAR_NAMESPACE + d = newGlobalDictionary(); +#else + d = PyModule_GetDict(PyImport_AddModule("__main__")); +#endif + + ret = BPY_runPython(text, d); + + if (!ret) { +#ifdef CLEAR_NAMESPACE + releaseGlobalDictionary(d); +#endif + BPY_Err_Handle(text); + Py_Finalize(); + initBPythonInterpreter(); + return NULL; + } + else + Py_DECREF(ret); + + + /* The following lines clear the global name space of the python + * interpreter. This is desired to release objects after execution + * of a script (remember that each wrapper object increments the refcount + * of the Blender Object. + + * Exception: scripts that use the GUI rely on the + * persistent global namespace, so they need a workaround: The namespace + * is released when the GUI is exit. + * See opy_draw.c:Method_Register() + * + */ + +#ifdef CLEAR_NAMESPACE + if (st->flags & ST_CLEAR_NAMESPACE) { + releaseGlobalDictionary(d); + garbage_collect(getGlobal()->main); + } +#endif + + return d; +} + +/****************************************/ +/* SCRIPTLINKS */ + +static void do_all_scriptlist(ListBase* list, short event) +{ + ID *id; + + id = list->first; + while (id) + { + BPY_do_pyscript (id, event); + id = id->next; + } +} + +void BPY_do_all_scripts(short event) +{ + do_all_scriptlist(getObjectList(), event); + do_all_scriptlist(getLampList(), event); + do_all_scriptlist(getCameraList(), event); + do_all_scriptlist(getMaterialList(), event); + do_all_scriptlist(getWorldList(), event); + + BPY_do_pyscript(&scene_getCurrent()->id, event); +} + + +char *event_to_name(short event) +{ + switch (event) { + case SCRIPT_FRAMECHANGED: + return "FrameChanged"; + case SCRIPT_ONLOAD: + return "OnLoad"; + case SCRIPT_REDRAW: + return "Redraw"; + default: + return "Unknown"; + } +} + + +void BPY_do_pyscript(ID *id, short event) +{ + int i, offset; + char evName[24] = ""; + char* structname = NULL; + ScriptLink* scriptlink; + PyObject *globaldict; + + switch(GET_ID_TYPE(id)) { + case ID_OB: structname= "Object"; break; + case ID_LA: structname= "Lamp"; break; + case ID_CA: structname= "Camera"; break; + case ID_MA: structname= "Material"; break; + case ID_WO: structname= "World"; break; + case ID_SCE: structname= "Scene"; break; + default: return; + } + + offset = BLO_findstruct_offset(structname, "scriptlink"); + if (offset < 0) + { + BPY_warn(("Internal error, unable to find script link\n")); + return; + } + scriptlink = (ScriptLink*) (((char*)id) + offset); + + /* no script provided */ + if (!scriptlink->totscript) return; + +/* Debugging output */ + switch (event) + { + case SCRIPT_FRAMECHANGED: + strcpy(evName, "SCRIPT_FRAMECHANGED"); + BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName)); + break; + case SCRIPT_ONLOAD: + strcpy(evName, "SCRIPT_ONLOAD"); + BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName)); + break; + case SCRIPT_REDRAW: + strcpy(evName, "SCRIPT_REDRAW"); + BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName)); + break; + default: + BPY_debug(("do_pyscript(): This should not happen !!!")); + break; + } + +/* END DEBUGGING */ +#ifndef SHAREDMODULE + set_scriptlinks(id, event); +#endif + disable_where_script(1); + for (i = 0; i < scriptlink->totscript; i++) + { + if (scriptlink->flag[i] == event && scriptlink->scripts[i]) + { + BPY_debug(("Evaluate script \"%s\" ...\n", + getIDName(scriptlink->scripts[i]))); + script_link_id = id; +#ifdef CLEAR_NAMESPACE + globaldict = newGlobalDictionary(); +#else + globaldict = PyModule_GetDict(PyImport_AddModule("__main__")); +#endif + BPY_runPython((Text*) scriptlink->scripts[i], globaldict); +#ifdef CLEAR_NAMESPACE + releaseGlobalDictionary(globaldict); +#endif + + script_link_id = NULL; + BPY_debug(("... done\n")); + } + } +#ifndef SHAREDMODULE + release_scriptlinks(id); +#endif + disable_where_script(0); +} + +void BPY_clear_bad_scriptlink(ID *id, Text *byebye) +{ + ScriptLink* scriptlink; + int offset = -1; + char* structname = NULL; + int i; + + switch (GET_ID_TYPE(id)) { + case ID_OB: structname = "Object"; break; + case ID_LA: structname = "Lamp"; break; + case ID_CA: structname = "Camera"; break; + case ID_MA: structname = "Material"; break; + case ID_WO: structname = "World"; break; + case ID_SCE: structname = "Scene"; break; + } + + if (!structname) return; + + offset= BLO_findstruct_offset(structname, "scriptlink"); + + if (offset<0) return; + + scriptlink= (ScriptLink *) (((char *)id) + offset); + + for(i=0; i<scriptlink->totscript; i++) + if ((Text*)scriptlink->scripts[i] == byebye) + scriptlink->scripts[i] = NULL; +} + +void BPY_clear_bad_scriptlist(ListBase *list, Text *byebye) +{ + ID *id; + + id= list->first; + while (id) + { + BPY_clear_bad_scriptlink(id, byebye); + id= id->next; + } +} + +void BPY_clear_bad_scriptlinks(Text *byebye) +{ + BPY_clear_bad_scriptlist(getObjectList(), byebye); + BPY_clear_bad_scriptlist(getLampList(), byebye); + BPY_clear_bad_scriptlist(getCameraList(), byebye); + BPY_clear_bad_scriptlist(getMaterialList(), byebye); + BPY_clear_bad_scriptlist(getWorldList(), byebye); + BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye); + allqueue(REDRAWBUTSSCRIPT, 0); +} + +void BPY_free_scriptlink(ScriptLink *slink) +{ + if (slink->totscript) + { + if(slink->flag) MEM_freeN(slink->flag); + if(slink->scripts) MEM_freeN(slink->scripts); + } +} + +void BPY_copy_scriptlink(ScriptLink *scriptlink) +{ + void *tmp; + + if (scriptlink->totscript) + { + tmp = scriptlink->scripts; + scriptlink->scripts = MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL"); + memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript); + + tmp = scriptlink->flag; + scriptlink->flag = MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF"); + memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript); + } +} + +/* + * Python alien graphics format conversion framework + * + * $Id$ + * + * + * + */ + +/* import importloader module with registered importers */ +#include "BPY_extern.h" +#include "Python.h" + + +int BPY_call_importloader(char *name) +{ + PyObject *mod, *tmp, *meth, *args; + int i, success = 0; + + init_syspath(); + mod = PyImport_ImportModule("Converter.importloader"); + if (mod) { + meth = PyObject_GetAttrString(mod, "process"); // new ref + args = Py_BuildValue("(s)", name); + tmp = PyEval_CallObject(meth, args); + Py_DECREF(meth); + if (PyErr_Occurred()) { + PyErr_Print(); + } + + if (tmp) { + i = PyInt_AsLong(tmp); + if (i) + success = 1; + Py_DECREF(tmp); + } + Py_DECREF(mod); + } else { + PyErr_Print(); + BPY_warn(("couldn't import 'importloader' \n")); + } + return success; +} + +// more to come... diff --git a/source/blender/bpython/intern/BPY_main.h b/source/blender/bpython/intern/BPY_main.h new file mode 100644 index 00000000000..526aa21df8f --- /dev/null +++ b/source/blender/bpython/intern/BPY_main.h @@ -0,0 +1,86 @@ +/* BlenderPython Main routine header * + $Id$ + + ***** BEGIN GPL/BL DUAL 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. The Blender + Foundation also sells licenses for use in proprietary software under + the Blender License. See http://www.blender.org/BL/ for information + about this. + + 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. + + The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + All rights reserved. + + The Original Code is: all of this file. + + Contributor(s): none yet. + + ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +// Note: Functions prefixed with BPY_ are called from blenkernel routines */ + + +#include "Python.h" /* The python includes themselves. */ +#include "compile.h" /* to give us PyCodeObject */ +#include "eval.h" /* for PyEval_EvalCode.h */ + +/* blender stuff */ +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_fileops.h" /* string handling of filenames */ + +#include "BKE_bad_level_calls.h" +// #include "BKE_editmesh.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BLO_genfile.h" // for BLO_findstruct_offset only +#include "BKE_text.h" +#include "BKE_displist.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_object.h" +#include "BKE_screen.h" +#include "BKE_scene.h" +#include "BKE_library.h" +#include "BKE_text.h" + +#include "b_interface.h" + +/* prototypes of externally used functions are HERE */ +#include "BPY_extern.h" + + /* I just chucked some prototypes + * here... not sure where they should + * really be. -zr + */ +extern struct ID * script_link_id; + +extern PyObject *g_blenderdict; +extern int g_window_redrawn; +extern int disable_force_draw; + +void window_update_curCamera(Object *); +PyObject *ConstObject_New(void); +void insertConst(PyObject *dict, char *name, PyObject *item); +PyObject *Windowmodule_Redraw(PyObject *self, PyObject *args); + +char *event_to_name(short event); +void syspath_append(PyObject *dir); +void init_syspath(void); +void set_scriptlinks(ID *id, short event); +void release_scriptlinks(ID *id); diff --git a/source/blender/bpython/intern/BPY_modules.h b/source/blender/bpython/intern/BPY_modules.h new file mode 100644 index 00000000000..98f9170fe9b --- /dev/null +++ b/source/blender/bpython/intern/BPY_modules.h @@ -0,0 +1,47 @@ +/* Prototypes for all fixed module init routines + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * these prototypes and init functions should be homogenized + */ + +extern PyObject *init_blender(void); +extern PyObject *init_py_nmesh(void); +extern PyObject *init_py_draw(void); +extern PyObject *init_py_bgl(void); +extern PyObject *initWindow(void); +extern PyObject *initImage(void); +extern PyObject *init_types(PyObject *dict); +void init_py_vector(void); +void init_py_matrix(void); +void init_Datablockmodules(PyObject *dict); +void initGUI(void); + + + diff --git a/source/blender/bpython/intern/BPY_object.c b/source/blender/bpython/intern/BPY_object.c new file mode 100644 index 00000000000..d0184f9b729 --- /dev/null +++ b/source/blender/bpython/intern/BPY_object.c @@ -0,0 +1,499 @@ +/** Object module; access to Object objects in Blender + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ +#include "Python.h" +#include "BPY_macros.h" +#include "MEM_guardedalloc.h" +#include "opy_vector.h" /* matrix datatypes */ + +#include "b_interface.h" // most datatypes + +#include "opy_datablock.h" + +#include "BLI_arithb.h" /* Mat4Invert */ + +/* PROTOS */ + + +/* ------------------------------------------------------------------------ */ + +/**************************************************/ +/* Object properties for access by datablock code */ + +#define NULLFUNC 0 +#define NULLHANDLING 0 + +/* structure: see opy_datablock.h */ +/* attrname, DNA_membername, type stype, min, max, index,dlist, + handlingflag, extra1Ptr, extra2Ptr, extra3Ptr */ + +DataBlockProperty Object_Properties[]= { + {"LocX", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"LocY", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"LocZ", "loc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"loc", "loc[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"dLocX", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"dLocY", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"dLocZ", "dloc[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"dloc", "dloc[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"RotX", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"RotY", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"RotZ", "rot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"rot", "rot[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"dRotX", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"dRotY", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"dRotZ", "drot[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"drot", "drot[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"SizeX", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"SizeY", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"SizeZ", "size[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"size", "size[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"dSizeX", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {0}, {3, -sizeof(float)}}, + {"dSizeY", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {1}, {3, -sizeof(float)}}, + {"dSizeZ", "dsize[3]", DBP_TYPE_FLO, 0, 0.0, 0.0, {2}, {3, -sizeof(float)}}, + {"dsize", "dsize[3]", DBP_TYPE_VEC, 0, 3.0}, + + {"EffX", "effx", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr}, + {"EffY", "effy", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr}, + {"EffZ", "effz", DBP_TYPE_FLO, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr}, + + {"Layer", "layer", DBP_TYPE_INT, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr}, + {"layer", "layer", DBP_TYPE_INT, DBP_TYPE_FUN, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, 0, Object_special_setattr}, + + {"parent", "*parent", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + {"track", "*track", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + {"data", "*data", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {"mat", "matrix", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, newMatrixObject}, + {"matrix", "matrix", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_FUNC, Object_special_getattr, newMatrixObject}, + + {"colbits", "colbits", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"drawType", "dt", DBP_TYPE_CHA, 0, 0.0, 0.0}, + {"drawMode", "dtx", DBP_TYPE_CHA, 0, 0.0, 0.0}, + + {NULL} +}; + +/*************************/ +/* Object module methods */ + +DATABLOCK_GET(Objectmodule, object, getObjectList()) + +char Objectmodule_New_doc[] = "(type) - Add a new object of type 'type' in the current scene"; +static PyObject *Objectmodule_New(PyObject *self, PyObject *args) +{ + Object *ob; + int type; + + if (!PyArg_ParseTuple(args, "i", &type)) { + PyErr_SetString(PyExc_TypeError, "type expected"); + return 0; + } + /* add object */ + ob = object_new(type); + return DataBlock_fromData(ob); +} + +static char Objectmodule_getSelected_doc[]= +"() - Returns a list of selected Objects in the active layer(s)\n\ +The active object is the first in the list, if visible"; + +static PyObject *Objectmodule_getSelected (PyObject *self, PyObject *args) +{ + PyObject *ob, *list; + Base *base; + Object *tmp; + + list= PyList_New(0); + + if (ActiveBase && SelectedAndLayer(ActiveBase)) { + tmp = ActiveObject; /* active object is first in list */ + if (!tmp) goto no_selection; + ob = DataBlock_fromData(tmp); + PyList_Append(list, ob); Py_DECREF(ob); // because previous call increfs + } + + base = FirstBase; + while (base) { + if (SelectedAndLayer(base) && base != ActiveBase) { + PyObject *ob = DataBlock_fromData(ObjectfromBase(base)); + if (!ob) goto no_selection; + PyList_Append(list, ob); Py_DECREF(ob); + } + base= base->next; + } + return list; +no_selection: + Py_DECREF(list); + Py_INCREF(Py_None); + return Py_None; + +} + + +struct PyMethodDef Objectmodule_methods[] = { + {"New", Objectmodule_New, METH_VARARGS, Objectmodule_New_doc}, + // emulation : + {"Get", Objectmodule_get, METH_VARARGS, Objectmodule_get_doc}, // XXX + {"get", Objectmodule_get, METH_VARARGS, Objectmodule_get_doc}, + {"getSelected", Objectmodule_getSelected, METH_VARARGS, Objectmodule_getSelected_doc}, + {NULL, NULL} +}; + +/*************************/ +/* Object object methods */ + +/* Object_get is defined as macro; see opy_datablock.h */ + + +static char Object_getType_doc[] = "() - returns Object type"; + +static PyObject *Object_getType(PyObject *self, PyObject *args) +{ + Object *ob= PYBLOCK_AS_OBJECT(self); + return Py_BuildValue("i", (short) ob->type); +} + +static char Object_getMatrix_doc[] = "() - returns 4D matrix of object"; + +static PyObject *Object_getMatrix(PyObject *self, PyObject *args) +{ + Object *ob= PYBLOCK_AS_OBJECT(self); + return newMatrixObject(ob->obmat); +} + +static char Object_getInverseMatrix_doc[] = "() - returns inverse 4D matrix of object"; + +static PyObject *Object_getInverseMatrix(PyObject *self, PyObject *args) +{ + Object *ob= PYBLOCK_AS_OBJECT(self); + float inverse[4][4]; + Mat4Invert(inverse, ob->obmat); + return newMatrixObject(inverse); +} + +static char Object_clrParent_doc[]= +"(mode = 0, fast = 0) - clears parent object.\n\ +If specified:\n\ + mode 2: keep object transform\n\ + fast > 0: don't update scene hierarchy (faster)\n\ +"; + +static PyObject *Object_clrParent(PyObject *self, PyObject *args) +{ + int mode = 0, ret; + int fast = 0; + Object *ob= PYBLOCK_AS_OBJECT(self); + + BPY_TRY(PyArg_ParseTuple(args, "|ii", &mode, &fast)); + ret = object_clrParent(ob, mode, fast); + return Py_BuildValue("i", ret); +} + +DATABLOCK_ASSIGN_IPO(Object, object) // defines Object_assignIpo + +static char Object_makeParent_doc[]= +"([obj1, obj2, ...], mode = 0, fast = 0) - makes 'self' a parent of the\n\ +objects in the list.\n\ +If specified:\n\ + mode <> 0: do not clear parent inverse\n\ + fast <> 0 : do not update scene hierarchy (faster)\n\ +\n\ +If fast is set, you will have to call Scene.getCurrent.update() before\n\ +redraw."; + +static PyObject *Object_makeParent(PyObject *self, PyObject *args) +{ + int i, ret; + PyObject *list; + int noninverse = 0; + int fast = 0; + + DataBlock *parblk = (DataBlock*) self; + + BPY_TRY(PyArg_ParseTuple(args, "O|ii", &list, &noninverse, &fast)); + if (!PySequence_Check(list)){ + PyErr_SetString(PyExc_TypeError, "expects a list of objects"); + return 0; + } + + for (i = 0; i < PySequence_Length(list); i ++) { + DataBlock *childblk = (DataBlock *) PySequence_GetItem(list, i); + + if (!DataBlock_Check(childblk)) { + PyErr_SetString(PyExc_TypeError, "Object Type expected"); + return 0; + } + ret = object_makeParent((Object *) parblk->data, (Object *) childblk->data, noninverse, fast); + + Py_DECREF((PyObject *) childblk); // don't need it anymore + if (ret == 0) { // could not parent + PyErr_SetString(PyExc_RuntimeError, "parenting failed!"); + return 0; + } + } + + if (PyErr_Occurred()) { + PyErr_Print(); + } + return Py_BuildValue("i", 1); +} + +static char Object_getMaterials_doc[] = "() - returns a list of object materials"; + +static PyObject *Object_getMaterials(PyObject *self, PyObject *args) +{ + DataBlock *objectblk = (DataBlock*) self; + Object *object = PYBLOCK_AS_OBJECT(objectblk); + return PyList_fromMaterialList(object->mat, object->totcol); +} + +static char Object_setMaterials_doc[] = "(materialList) - sets object materials"; + +static PyObject *Object_setMaterials(PyObject *self, PyObject *args) +{ + int len; + int ret; + DataBlock *objectblk = (DataBlock*) self; + Object *object = PYBLOCK_AS_OBJECT(objectblk); + PyObject *list; + Material **matlist; + + BPY_TRY(PyArg_ParseTuple(args, "O!", &PyList_Type, &list)); + len = PySequence_Length(list); + if (len) { + matlist = newMaterialList_fromPyList(list); + if (!matlist) { + PyErr_SetString(PyExc_TypeError, + "materialList must be a list of valid materials!"); + return 0; + } + ret = object_setMaterials(object, matlist, len); + } else { + ret = 0; + } + return Py_BuildValue("i", ret); +} + +static char Object_copy_doc[] = "() - returns a copy of the object, sharing the same data"; + +static PyObject *Object_copy(PyObject *self, PyObject *args) +{ + Object *new; + + DataBlock *objectblk = (DataBlock*) self; + Object *object = PYBLOCK_AS_OBJECT(objectblk); + + new = object_copy(object); + return DataBlock_fromData(new); +} + +static char Object_shareFrom_doc[] = "(obj) - link data of 'self' with data of 'obj' -- \n\ +only if of same type!"; + +static PyObject *Object_shareFrom(PyObject *self, PyObject *args) +{ + DataBlock *blockA = (DataBlock*) self; + DataBlock *blockB; + Object *object, *other; + int t; + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB)); + + if (!DataBlock_isType(blockB, ID_OB)) { + PyErr_SetString(PyExc_TypeError, "Argument 1 is not of type 'Object'"); + return NULL; + } + + object = PYBLOCK_AS_OBJECT(blockA); + other = PYBLOCK_AS_OBJECT(blockB); + + if (other->type != object->type) { + PyErr_SetString(PyExc_TypeError, "Objects are not of same data type"); + return NULL; + } + t = object->type; + switch (t) { + case OB_MESH: + return Py_BuildValue("i", object_linkdata(object, other->data)); + default: + PyErr_SetString(PyExc_TypeError, "Type not supported"); + return NULL; + } +} + +/******************/ +/* get & set attr */ + +static float g_zero_float= 0.0; + +/* Object attributes functions which require getter/setter C functions + different from the access provided by DataBlock support */ + +/* get special attributes through datablock property structure */ + +void *Object_special_getattr(void *vdata, char *name) +{ + Object *ob= (Object *) vdata; + int scriptflag; + + if (STREQ(name, "layer")) { + return &ob->lay; + + } else if (strncmp(name, "eff", 3)==0) { + Ika *ika= ob->data; + + if (ob->type==OB_IKA && ika) { + if (name[3]=='x') return &ika->effg[0]; + else if (name[3]=='y') return &ika->effg[1]; + else if (name[3]=='z') return &ika->effg[2]; + } + + return &g_zero_float; + /* these only for compatibiliy... XXX */ + } else if (STREQ(name, "matrix")) { + scriptflag = during_script(); + disable_where_script(1); + where_is_object(ob); + disable_where_script(scriptflag); + + return &ob->obmat; + } else if (STREQ(name, "inverse") || STREQ(name, "inverseMatrix")) { + return Object_getInverseMatrix(vdata, 0); + } + /* end compatibility */ + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +int Object_special_setattr(void *vdata, char *name, PyObject *py_ob) +{ + Object *ob= (Object *) vdata; + + if (STREQ(name, "layer")) { + Base *base; + int ival; + + if (!PyArg_Parse(py_ob, "i", &ival)) return -1; + + ob->lay= ival; + // TODO this is old stuff, maybe move to update routine at end of + // script execution ? + base= (G.scene->base.first); + while (base) { + if (base->object == ob) base->lay= ob->lay; + base= base->next; + } + // end TODO + + return 0; + } else if (strncmp(name, "eff", 3)==0) { + Ika *ika= ob->data; + float fval; + + if (!PyArg_Parse(py_ob, "f", &fval)) return -1; + + if (ob->type==OB_IKA && ika) { + if (name[3]=='x') ika->effg[0]= fval; + else if (name[3]=='y') ika->effg[1]= fval; + else if (name[3]=='z') ika->effg[2]= fval; + + itterate_ika(ob); + } + return 0; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + + + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Object) + +struct PyMethodDef Object_methods[] = { + MethodDef(makeParent), + MethodDef(copy), + MethodDef(shareFrom), + MethodDef(getMatrix), + MethodDef(getType), + MethodDef(getInverseMatrix), + MethodDef(clrParent), + MethodDef(assignIpo), + MethodDef(clrIpo), + MethodDef(getMaterials), + MethodDef(setMaterials), + {NULL, NULL} +}; + +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(OB_##name)) + +PyObject *initObject(void) +{ + PyObject *mod, *dict, *d; + + mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Object", Objectmodule_methods); + dict= PyModule_GetDict(mod); + d = ConstObject_New(); + PyDict_SetItemString(dict, "Types", d); + BPY_ADDCONST(d, EMPTY); + BPY_ADDCONST(d, MESH); + BPY_ADDCONST(d, LAMP); + BPY_ADDCONST(d, CAMERA); + + d = ConstObject_New(); + PyDict_SetItemString(dict, "DrawTypes", d); + /* dt flags */ + BPY_ADDCONST(d, BOUNDBOX); + BPY_ADDCONST(d, WIRE); + BPY_ADDCONST(d, SOLID); + BPY_ADDCONST(d, SHADED); + BPY_ADDCONST(d, TEXTURE); + d = ConstObject_New(); + PyDict_SetItemString(dict, "DrawModes", d); + /* dtx flags */ + BPY_ADDCONST(d, BOUNDBOX); + BPY_ADDCONST(d, AXIS); + BPY_ADDCONST(d, TEXSPACE); + insertConst(d, "NAME", PyInt_FromLong(OB_DRAWNAME)); + return mod; +} + diff --git a/source/blender/bpython/intern/BPY_scene.c b/source/blender/bpython/intern/BPY_scene.c new file mode 100644 index 00000000000..19e992e6bb1 --- /dev/null +++ b/source/blender/bpython/intern/BPY_scene.c @@ -0,0 +1,506 @@ +/** Scene module; access to Scene objects in Blender + * + * Scene objects are no longer DataBlock objects, but referred + * by name. This makes it a little slower, but safer - Scene properties + * can no longer be accessed after a Scene was deleted. + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#include "Python.h" + +#include "BKE_scene.h" +#include "BIF_drawscene.h" + +#include "BSE_headerbuttons.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "opy_datablock.h" +#include "b_interface.h" + +#include "BPY_macros.h" +#include "BPY_window.h" + +/* DEFINES */ + +#define CHECK_VALIDSCENE(x) CHECK_VALIDDATA(x, \ + "Scene was deleted!") + +#define PyScene_AsScene(x) \ + getSceneByName(((PyScene *) x)->name) + +/* PROTOS */ + +PyObject *PyScene_FromScene(Scene *scene); + +/************************/ +/* Helper routines */ + +/* returns a python list of the objects of the Base 'base' */ + +static PyObject *objectlist_from_base(Base *base) +{ + PyObject *pylist= PyList_New(0); + PyObject *b; + + while (base) { + b = (PyObject *) DataBlock_fromData(base->object); + PyList_Append(pylist, b); + Py_XDECREF(b); // because PyList_Append increfs! + base = base->next; + } + return pylist; +} + +/* Scene object */ + +typedef struct { + PyObject_VAR_HEAD + char name[32]; +} PyScene; + +static PyObject *newPyScene(char *name); + +/** Returns scene by name. Can be NULL if not found */ +Scene *getSceneByName(char *name) +{ + return (Scene *) getFromList(getSceneList(), name); +} + +/************************/ +/* Scene object methods */ + +static char Scene_getChildren_doc[] = +"() - returns list of scene children objects"; + +static PyObject *Scene_getChildren(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "")); + return objectlist_from_base(scene->base.first); +} + +static char Scene_getCurrentCamera_doc[] = +"() - returns current active camera"; + +static PyObject *Scene_getCurrentCamera(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + Object *object; + + CHECK_VALIDSCENE(scene) + + object = scene->camera; + if (!object) { + Py_INCREF(Py_None); + return Py_None; + } + return DataBlock_fromData(object); +} + +static char Scene_setCurrentCamera_doc[] = +"(camera) - sets current active camera. 'camera' must be a valid camera\n\ +Object"; + +static PyObject *Scene_setCurrentCamera(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + Object *object; + DataBlock *block; + + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block)); + if (!DataBlock_isType(block, ID_OB)) { + PyErr_SetString(PyExc_TypeError, "Object type expected!"); + return NULL; + } + + object = PYBLOCK_AS_OBJECT(block); + + scene->camera = object; + if (scene_getCurrent() == scene) // update current scene display + window_update_curCamera(object); + + Py_INCREF(Py_None); + return Py_None; +} + +#define SCENE_GETDIR(name, elem) \ +static PyObject *Scene_get##name(PyObject *self, PyObject *args) \ +{ \ + Scene *scene = PyScene_AsScene(self); \ + CHECK_VALIDSCENE(scene) \ + return PyString_FromString(scene->elem); \ +} \ + +static char Scene_getRenderdir_doc[] = +"() - returns directory where rendered images are saved to"; + +SCENE_GETDIR(Renderdir, r.pic) + +static char Scene_getBackbufdir_doc[] = +"() - returns the Backbuffer images location"; + +SCENE_GETDIR(Backbufdir, r.backbuf) + +#define INVALID_FRAME -99999 + +static char Scene_frameSettings_doc[] = +"(start, end, current) - sets the scene's frame settings:\n\ + start : start frame\n\ + end : end frame\n\ + current: current frame\n\ +If a frame value is negative, it is not set.\n\ +\n\ +Return value: the current frame settings (start, end, current)"; + +static PyObject *Scene_frameSettings(PyObject *self, PyObject *args) +{ + RenderData *rd = 0; + int current = INVALID_FRAME; + int start = INVALID_FRAME; + int end = INVALID_FRAME; + Scene *scene = PyScene_AsScene(self); + + CHECK_VALIDSCENE(scene) + + rd = &scene->r; + + BPY_TRY(PyArg_ParseTuple(args, "|iii", &start, &end, ¤t)); + if (start > 0) { + rd->sfra = start; + } + if (end > 0) { + rd->efra = end; + } + if (current > 0) { + rd->cfra = current; + } + return Py_BuildValue("(iii)", rd->sfra, rd->efra, rd->cfra); +} + + +static char Scene_makeCurrent_doc[] = +"() - makes Scene the current Scene"; + +static PyObject *Scene_makeCurrent(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + + CHECK_VALIDSCENE(scene) + + set_scene(scene); + Py_INCREF(Py_None); + return Py_None; +} + +static char Scene_copy_doc[] = +"(duplicate_objects = 1) - make a copy of a scene\n\ +'The optional argument defines, how the scene's children objects are\n\ +duplicated:\n\ +\n\ +0: Link Objects\n\ +1: Link Object data\n\ +2: Full Copy"; + +static PyObject *Scene_copy(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + + int dup_objects = 0; + + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "|i", &dup_objects)); + + return PyScene_FromScene(copy_scene(scene, dup_objects)); +} + +static char Scene_update_doc[]= "() - Update scene\n\ +This function explicitely resorts the base list of a newly created object\n\ +hierarchy."; + +static PyObject *Scene_update(PyObject *self, PyObject *args) +{ + Scene *scene = PyScene_AsScene(self); + + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "")); + sort_baselist(scene); + Py_INCREF(Py_None); + return Py_None; +} + +static char Scene_link_doc[]= "(object) - Links object to scene"; + +/** Links an object with a scene */ +static PyObject *Scene_link(PyObject *self, PyObject *args) +{ + DataBlock *block; + Object *object; + Scene *scene = PyScene_AsScene(self); + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block)); + if (DataBlock_type(block) != ID_OB) { + PyErr_SetString(PyExc_TypeError, "link: invalid Object type"); + return NULL; + } + object = PYBLOCK_AS_OBJECT(block); + if (!scene_linkObject(scene, object)) + { + PyErr_SetString(PyExc_RuntimeError, "Object already in scene!"); + return NULL; + } + Py_INCREF(Py_None); + return Py_None; +} + +/** unlinks (removes) an object from a scene */ + +static char Scene_unlink_doc[]= "(object) - Unlinks object from scene"; + +static PyObject *Scene_unlink(PyObject *self, PyObject *args) +{ + PyObject *retval; + DataBlock *block; + Object *object; + Scene *scene = PyScene_AsScene(self); + CHECK_VALIDSCENE(scene) + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &block)); + if (DataBlock_type(block) != ID_OB) { + PyErr_SetString(PyExc_TypeError, "unlink: invalid Object type"); + return NULL; + } + object = PYBLOCK_AS_OBJECT(block); + + if (!scene_unlinkObject(scene, object)) + retval = Py_BuildValue("i", 0); + else + retval = Py_BuildValue("i", 1); + Py_INCREF(retval); + return retval; +} + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Scene) + +/* these are the scene object methods */ +static struct PyMethodDef Scene_methods[] = { + MethodDef(copy), + MethodDef(link), + MethodDef(unlink), + MethodDef(getChildren), + MethodDef(getCurrentCamera), + MethodDef(setCurrentCamera), + MethodDef(getRenderdir), + MethodDef(getBackbufdir), + MethodDef(frameSettings), + MethodDef(makeCurrent), + MethodDef(update), + {NULL, NULL} +}; + +static void PyScene_dealloc(PyObject *self) +{ + PyMem_DEL(self); +} + +static PyObject *PyScene_getattr(PyObject *self, char *attr) +{ + Scene *scene; + if (!strcmp(attr, "name")) { + return PyString_FromString(((PyScene *) self)->name); + } else if (!strcmp(attr, "users")) { + scene = PyScene_AsScene(self); + return PyInt_FromLong(getUsers(scene)); + } else if (!strcmp(attr, "block_type")) { + return Py_BuildValue("s", "Scene"); + } + return Py_FindMethod(Scene_methods, (PyObject *) self, attr); +} + +PyObject *PyScene_repr(PyScene *self) +{ + char s[256]; + Scene *scene = PyScene_AsScene(self); + if (scene) + sprintf (s, "[Scene %.32s]", getName(scene)); + else + sprintf (s, "[deleted Scene]"); + return Py_BuildValue("s", s); +} + +static PyTypeObject PyScene_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Scene", /*tp_name*/ + sizeof(PyScene), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) PyScene_dealloc, /*tp_dealloc*/ + (printfunc)0, /*tp_print*/ + (getattrfunc)PyScene_getattr, /*tp_getattr*/ + (setattrfunc)0, /*tp_setattr*/ + (cmpfunc)0, /*tp_compare*/ + (reprfunc)PyScene_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc)0, /*tp_hash*/ + (ternaryfunc)0, /*tp_call*/ + (reprfunc)0, /*tp_str*/ + + /* Space for future expansion */ + 0L,0L,0L,0L, + 0 /* Documentation string */ +}; + +static PyObject *newPyScene(char *name) +{ + PyScene *scene = PyObject_NEW(PyScene, &PyScene_Type); + strncpy(scene->name, name, 31); + return (PyObject *) scene; +} + +PyObject *PyScene_FromScene(Scene *scene) +{ + if (scene) + return newPyScene(getName(scene)); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +PyObject *PyScene_FromVoid(void *scene) +{ + return PyScene_FromScene((Scene *) scene); +} + + +/************************/ +/* Scene module methods */ + +static char Scenemodule_get_doc[] = +"(name = None) - get Scene 'name' from Blender, if 'name' specified.\n\ +Otherwise, a list of all Scenes is returned"; + +static PyObject *Scenemodule_get(PyObject *self, PyObject *args) +{ + char *name= NULL; + BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); + + if (name) { + return PyScene_FromScene(getSceneByName(name)); + } else { + return BPY_PyList_FromIDList(getSceneList(), PyScene_FromVoid); + } +} + +static char Scenemodule_New_doc[] = +"(name = None) - Create new scene with (optionally given)\n\ +name."; + +static PyObject *Scenemodule_New(PyObject *self, PyObject *args) +{ + Scene *scene; + char *name = "Scene"; + + BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); + scene = add_scene(name); + return newPyScene(name); +} + +static char Scenemodule_getCurrent_doc[] = +"() - returns currently active Scene"; + +static PyObject *Scenemodule_getCurrent(PyObject *self, PyObject *args) +{ + return newPyScene(getName(scene_getCurrent())); +} + +static char Scenemodule_unlink_doc[] = +"(scene) - deletes the Scene 'scene' from Blender\n\ +The Scene must be empty before removing it"; + +static PyObject *Scenemodule_unlink(PyObject *self, PyObject *args) +{ + PyObject *sceneobj; + Scene *scene; + + if(!PyArg_ParseTuple(args, "O!", &PyScene_Type, &sceneobj)) { + PyErr_SetString(PyExc_TypeError, "Scene object expected!"); + return NULL; + } + + scene = PyScene_AsScene(sceneobj); + free_libblock(getSceneList(), scene); + Py_INCREF(Py_None); + return Py_None; +} + + +/*****************/ +/* METHOD TABLES */ + +/* these are the module methods */ + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Scenemodule) + +struct PyMethodDef Scenemodule_methods[] = { + MethodDef(get), + MethodDef(getCurrent), + MethodDef(New), + MethodDef(unlink), + {NULL, NULL} +}; + +PyObject *initScene() +{ + PyObject *mod; + PyScene_Type.ob_type = &PyType_Type; + mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Scene", + Scenemodule_methods); + return mod; +} + + diff --git a/source/blender/bpython/intern/BPY_text.c b/source/blender/bpython/intern/BPY_text.c new file mode 100644 index 00000000000..855e12a6b9f --- /dev/null +++ b/source/blender/bpython/intern/BPY_text.c @@ -0,0 +1,295 @@ +/** Text buffer module; access to Text buffers in Blender + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + * The ownership relations of a Text buffer are in Blender pretty clear: + * The Text editor is ALWAYS the container for all text objects. + * Currently, the Text object is implemented as a free object though, as + * the ownership of a Text might change in future. The reference counting of + * a Text object IN BLENDER is not really maintained though (for the above ownership + * reason). + * This introduces a problem if a Text object is accessed after it was actually + * deleted. Currently, a 'guard' is implemented for access after deletion INSIDE + * A SCRIPT. The Blender GUI is not aware of the wrapper though, so if a Text buffer + * is cleared while the script is accessing the wrapper, bad results are expected. + * BUT: This currently can not happen, unless a Python script is running in the + * background as a separate thread... + * + * TODO: + * + * either a): + * figure out ownership and implement each access to the text buffer by + * name and not by reference (pointer). This will require quite some additions + * in the generic DataBlock access (opy_datablock.c) + * + * or b): + * implement reference counting for text buffers properly, so that a deletion + * of a text buffer by the GUI does not result in a release of the actual + * Text object, but by a DECREF. The garbage collector (or wrapper deletion method) + * will then free the Text object. + * + * To be discussed and evaluated. + * + * $Id$ + * + */ + + +#include "Python.h" +#include "stringobject.h" + +#include "BPY_macros.h" +#include "BKE_text.h" +#include "BIF_drawtext.h" +#include "DNA_text_types.h" +#include "BPY_extern.h" +#include "BKE_sca.h" + +#include "b_interface.h" +#include "opy_datablock.h" + +DATABLOCK_GET(Textmodule, text object, getTextList()) + +#define CHECK_VALIDTEXT(x) CHECK_VALIDDATA(x, \ + "Text was deleted; illegal access!") + +#define OFF 1 + +static char Textmodule_New_doc[] = +"(name = None, follow = 0) - Create new text buffer with (optionally given)\n\ +name.\n\ +If 'follow' == 1, the text display always follows the cursor"; + +static PyObject *Textmodule_New(PyObject *self, PyObject *args) +{ + Text *text; + PyObject *textobj; + PyObject *name = NULL; + int follow = 0; + + text = add_empty_text(); + BPY_TRY(PyArg_ParseTuple(args, "|O!i", &PyString_Type, &name, &follow)); + textobj = DataBlock_fromData(text); + if (follow) { + text->flags |= TXT_FOLLOW; + } + if (name) { + DataBlock_setattr(textobj, "name", name); + } + return textobj; +} + +static char Textmodule_unlink_doc[] = +"(text) - remove text object 'text' from the text window"; + +/** This function removes the text entry from the text editor. + * The text is not freed here, but inside the garbage collector + */ + +static PyObject *Textmodule_unlink(PyObject *self, PyObject *args) +{ + PyObject *textobj; + Text *text; + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &textobj)); + if (!DataBlock_isType((DataBlock *) textobj, ID_TXT)) { + PyErr_SetString(PyExc_TypeError, "Text object expected!"); + return NULL; + } + + text = PYBLOCK_AS_TEXT(textobj); + BPY_clear_bad_scriptlinks(text); + free_text_controllers(text); + unlink_text(text); + /* We actually should not free the text object here, but let the + * __del__ method of the wrapper do the job. This would require some + * changes in the GUI code though.. + * So we mark the wrapper as invalid by setting wrapper->data = 0 */ + free_libblock(getTextList(), text); + MARK_INVALID(textobj); + + Py_INCREF(Py_None); + return Py_None; +} + + +/* these are the module methods */ +struct PyMethodDef Textmodule_methods[] = { + {"get", Textmodule_get, METH_VARARGS, Textmodule_get_doc}, + {"New", Textmodule_New, METH_VARARGS, Textmodule_New_doc}, + {"unlink", Textmodule_unlink, METH_VARARGS, Textmodule_unlink_doc}, + {NULL, NULL} +}; + +// Text object properties + +DataBlockProperty Text_Properties[]= { + {NULL} +}; + +/* This is uncommented only for an example on how (probably) not to + * do it :-) + * It's a bad idea in this case to have a wrapper object destroy its wrapped object + * because checks have to be done whether the wrapper is still accessed after + * the wrapped objects deletion. + * Better: unlink the object from it's owner: Blender.Text.unlink(text) + * That way the object is not yet freed, but its refcount set to 0. + * The garbage collector takes care of the rest.. + * But it has to be made sure that the wrapper object is no longer kept around + * after the script ends. + * + +static char Text_delete_doc[] = +"() - delete text from Text window"; + +static PyObject *Text_delete(PyObject *self, PyObject *args) +{ + Text *text = PYBLOCK_AS_TEXT(self); + // we have to check for validity, as the Text object is only a + // descriptor... + CHECK_VALIDTEXT(text) + BPY_TRY(PyArg_ParseTuple(args, "")); + BPY_clear_bad_scriptlinks(text); + free_text_controllers(text); + unlink_text(text); + free_libblock(&getGlobal()->main->text, text); + ((DataBlock *) self)->data = NULL; + Py_INCREF(Py_None); + return Py_None; +} + +*/ + +/** This method gets called on the wrapper objects deletion. + * Here we release the Text object if its refcount is == 0 + + -- CURRENTLY UNCOMMENTED -- needs change in Blender kernel.. + +static PyObject *Text_del(PyObject *self, PyObject *args) +{ + Text *text = PYBLOCK_AS_TEXT(self); + if (BOB_REFCNT((ID *) text) == 0) { + free_libblock(&getGlobal()->main->text, text); + } + Py_INCREF(Py_None); + return Py_None; +} +*/ + +static char Text_clear_doc[] = +"() - clear the text buffer"; + +static PyObject *Text_clear(PyObject *self, PyObject *args) +{ + Text *text = PYBLOCK_AS_TEXT(self); + int oldstate; + CHECK_VALIDTEXT(text) + + oldstate = txt_get_undostate(); + txt_set_undostate(OFF); + txt_sel_all(text); + txt_cut_sel(text); + txt_set_undostate(oldstate); + + Py_INCREF(Py_None); + return Py_None; +} + +static char Text_set_doc[] = +"(name, val) - set attribute name to val"; + +static PyObject *Text_set(PyObject *self, PyObject *args) +{ + int ival; + char *attr; + Text *text = PYBLOCK_AS_TEXT(self); + + BPY_TRY(PyArg_ParseTuple(args, "si", &attr, &ival)); + if (STREQ("follow_cursor", attr)) { + if (ival) { + text->flags |= TXT_FOLLOW; + } else { + text->flags &= TXT_FOLLOW; + } + } + Py_INCREF(Py_None); + return Py_None; +} + +static char Text_write_doc[] = +"(line) - append string 'line' to the text buffer"; + +static PyObject *Text_write(PyObject *self, PyObject *args) +{ + char *str; + Text *text = PYBLOCK_AS_TEXT(self); + int oldstate; + + CHECK_VALIDTEXT(text) + + BPY_TRY(PyArg_ParseTuple(args, "s", &str)); + oldstate = txt_get_undostate(); + txt_insert_buf(text, str); + txt_move_eof(text, 0); + txt_set_undostate(oldstate); + + Py_INCREF(Py_None); + return Py_None; +} + +static char Text_asLines_doc[] = +"() - returns the lines of the text buffer as list of strings"; + +static PyObject *Text_asLines(PyObject *self, PyObject *args) +{ + TextLine *line; + PyObject *list, *ob; + Text *text = (Text *) ((DataBlock *) self)->data; + + CHECK_VALIDTEXT(text) + + line = text->lines.first; + list= PyList_New(0); + while (line) { + ob = Py_BuildValue("s", line->line); + PyList_Append(list, ob); + line = line->next; + } + return list; +} + +/* these are the text object methods */ +struct PyMethodDef Text_methods[] = { + {"clear", Text_clear, METH_VARARGS, Text_clear_doc}, + {"write", Text_write, METH_VARARGS, Text_write_doc}, + {"set", Text_set, METH_VARARGS, Text_set_doc}, + {"asLines", Text_asLines, METH_VARARGS, Text_asLines_doc}, + {NULL, NULL} +}; + diff --git a/source/blender/bpython/intern/BPY_tools.c b/source/blender/bpython/intern/BPY_tools.c new file mode 100644 index 00000000000..5a2c483607c --- /dev/null +++ b/source/blender/bpython/intern/BPY_tools.c @@ -0,0 +1,106 @@ +/* python API tool subroutines + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "BKE_global.h" +#include "BPY_tools.h" + +/* These should all have BPY prefixes later on */ + +PyObject *BPY_incr_ret(PyObject *ob) { + Py_INCREF(ob); + return ob; +} + +PyObject *BPY_err_ret_ob(PyObject *type, char *err) { + PyErr_SetString(type, err); + return NULL; +} + +int py_err_ret_int(PyObject *type, char *err) { + PyErr_SetString(type, err); + return -1; +} + +int BPY_check_sequence_consistency(PyObject *seq, PyTypeObject *against) +{ + PyObject *ob; + int len= PySequence_Length(seq); + int i; + + for (i=0; i<len; i++) { + ob= PySequence_GetItem(seq, i); + if (ob->ob_type != against) { + Py_DECREF(ob); + return 0; + } + Py_DECREF(ob); + } + return 1; +} + +int BPY_parsefloatvector(PyObject *vec, float *ptr, int n) +{ + int i; + PyObject *o, *p; + char errstring[80]; + + if (PyArg_ParseTuple(vec, "ff|f", &ptr[0], &ptr[1], &ptr[2])) + return 0; + if (PyArg_Parse(vec, "O", &p)) { + if (PySequence_Check(p) && PySequence_Length(p) == n ) { + for (i = 0; i < n; i++) { + o = PySequence_GetItem(vec, i); + if (PyFloat_Check(o)) { + ptr[i] = PyFloat_AsDouble(o); + Py_DECREF(o); + } else { + Py_DECREF(o); + return py_err_ret_int(PyExc_AttributeError, "vector assignment wants floats"); + } + } + return 0; + } + } + + if (!PySequence_Check(p)) { + printf("invalid sequence"); + } + + /* errors: */ + sprintf(errstring, "Float vector tuple of length %d expected", n); + return py_err_ret_int(PyExc_AttributeError, errstring); +} + + + + diff --git a/source/blender/bpython/intern/BPY_tools.h b/source/blender/bpython/intern/BPY_tools.h new file mode 100644 index 00000000000..902c15686f0 --- /dev/null +++ b/source/blender/bpython/intern/BPY_tools.h @@ -0,0 +1,37 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +/* tools.c */ +extern PyObject *BPY_incr_ret (PyObject *ob); +extern PyObject *BPY_err_ret_ob (PyObject *type, char *err); +extern int py_err_ret_int (PyObject *type, char *err); +extern int BPY_check_sequence_consistency (PyObject *seq, PyTypeObject *against); +extern int BPY_parsefloatvector(PyObject *vec, float *ptr, int n); diff --git a/source/blender/bpython/intern/BPY_types.h b/source/blender/bpython/intern/BPY_types.h new file mode 100644 index 00000000000..217275f6e10 --- /dev/null +++ b/source/blender/bpython/intern/BPY_types.h @@ -0,0 +1,39 @@ +/* $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * API defined Object types + */ + +extern PyTypeObject PyIpoCurve_Type, PyBezTriple_Type; +extern PyTypeObject Button_Type, Buffer_Type; +extern PyTypeObject NMesh_Type, NMFace_Type, NMVert_Type, NMCol_Type; +extern PyTypeObject Vector_Type, Matrix_Type; + +extern PyTypeObject DataBlock_Type; +extern struct PyMethodDef Null_methods[]; diff --git a/source/blender/bpython/intern/BPY_window.h b/source/blender/bpython/intern/BPY_window.h new file mode 100644 index 00000000000..7a76dbd2e57 --- /dev/null +++ b/source/blender/bpython/intern/BPY_window.h @@ -0,0 +1,33 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +void window_update_curCamera(Object *camera); + diff --git a/source/blender/bpython/intern/Makefile b/source/blender/bpython/intern/Makefile new file mode 100644 index 00000000000..cb67e195aa8 --- /dev/null +++ b/source/blender/bpython/intern/Makefile @@ -0,0 +1,75 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# 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. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = bpython +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_1_C_WARNINGS) + +CPPFLAGS += -DFUTURE_PYTHON_API # see api.h for configuration +#CPPFLAGS += -DNO_RELEASE # see api.h for configuration + +# OpenGL and Python +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I$(NAN_BMFONT)/include/ + +# Reference to the types in makesdna and imbuf +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../imbuf +# This mod uses the BLI and BLO module +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../blenlib/intern +CPPFLAGS += -I$(NAN_BSP)/include # BSP includes +CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I../../blenloader +CPPFLAGS += -I../../bpython/include/ +# also avi is used +CPPFLAGS += -I../../avi +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include + +# we still refer to /include a bit... +CPPFLAGS += -I../../include + +# to include the render stuff: +CPPFLAGS += -I../../render/extern/include + +# path to our own external headerfiles +CPPFLAGS += -I.. + diff --git a/source/blender/bpython/intern/README b/source/blender/bpython/intern/README new file mode 100644 index 00000000000..c91e284cd27 --- /dev/null +++ b/source/blender/bpython/intern/README @@ -0,0 +1,22 @@ +Python API library // strubi@blender.nl +------------------ + + +NEW: + Several frozen Python byte code modules are now included in the + API under libfrozen.a. libbpython must be linked with libfrozen.a + from now on. + +source files: + +py_*.c: library files of Jan Walters API. Might undergo major replacements / surgery + later. +opy_*: the 'old' python API code. In fact quite nice and functional... -- needs + splitting up in API/ interfacing part. +BPY_*: these are the future API prefixes (newly written stuff that should be + Blender 3.0 compliant... -- no interface calls inside) + This is not YET quite true, for convenience, it still contains some direct + Blender access. +b_* : Blender interfacing / tools -- may contain dirty access hacks for blender + datastructures.. + diff --git a/source/blender/bpython/intern/api.h b/source/blender/bpython/intern/api.h new file mode 100644 index 00000000000..369e6175918 --- /dev/null +++ b/source/blender/bpython/intern/api.h @@ -0,0 +1,87 @@ +/* $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + * + * This headerfile defines the API status. + * Parts of the API can be compiled as dynamic module for testing -- + * see Makefile + */ + +#undef EXPERIMENTAL /* undefine this for release, please :-) */ + +/* Uncomment this if you want to have the new blender module +compiled static into Blender :*/ +/* #define SHAREDMODULE -- put into Makefile */ + +/* API configuration -- define in Makefile */ + +#ifdef SHAREDMODULE + #define BLENDERMODULE _Blender +#elif defined(CURRENT_PYTHON_API) + #define BLENDERMODULE Blender +#elif defined(FUTURE_PYTHON_API) + #define BLENDERMODULE _Blender +#else // FALLBACK + #define BLENDERMODULE Blender +#endif + +#define SUBMODULE(mod) (MODNAME(BLENDERMODULE) "." #mod) + +/* this macro defines the init routine for dynamically loaded modules; +example: + +void INITMODULE(BLENDERMODULE) -> void initBlender(void) +*/ + +#define _INITMODULE(x) init##x +#define INITMODULE(x) _INITMODULE(x) + +/* MODNAME(MODULE) stringifies the module definition, example: +MODNAME(BLENDERMODULE) -> "_Blender" +*/ + +#define _MODNAME(x) #x +#define MODNAME(x) _MODNAME(x) + +// module configuration -- TODO: this should be set later from the Makefile... +#if defined(__FreeBSD__) || defined(__linux__) || defined (__sgi) || defined(__sparc) +#define STATIC_TEXTTOOLS 1 +#endif + + +#define USE_NMESH 1 // still use NMesh structure for <mesh object>.data +#define CLEAR_NAMESPACE // undefine this if you still want the old dirty global + // namespace shared by ALL scripts. + + +// experimental sh*t: +#ifdef EXPERIMENTAL + #undef USE_NMESH +#endif diff --git a/source/blender/bpython/intern/b_import.c b/source/blender/bpython/intern/b_import.c new file mode 100644 index 00000000000..e490ee82338 --- /dev/null +++ b/source/blender/bpython/intern/b_import.c @@ -0,0 +1,191 @@ +/* $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + + Customized Blender import module, Sandbox model (TODO) + + TODO for Sandbox: + - only allow builtin modules to be imported + - only allow file read/write from certain directories + - alternative: override file read/write with popup requester + + main routine: + init_ourImport(); + +*/ + + + +#include "DNA_text_types.h" +#include "Python.h" +#include "import.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_text.h" + +#include "BLI_blenlib.h" // mallocs + +#include "BPY_macros.h" +#include "BPY_main.h" + +#include "b_import.h" + + +/* ---------------------------------------------------------------------------- */ + +PyObject *importText(char *name) +{ + Text *text; + char txtname[IDNAME]; + char *buf = NULL; + + + // TODO debug for too long names ! + + strncpy(txtname, name, IDNAME-4); + strcat(txtname, ".py"); + + text = (Text*) getGlobal()->main->text.first; + while(text) + { + if (STREQ(getName(text), txtname)) + break; + text = text->id.next; + } + if (!text) { + return NULL; + } + + if (!text->compiled) { + buf = txt_to_buf(text); + text->compiled = Py_CompileString(buf, getName(text), Py_file_input); + MEM_freeN(buf); + if (PyErr_Occurred()) + { + PyErr_Print(); + BPY_free_compiled_text(text); + return NULL; + } + } + BPY_debug(("import from TextBuffer: %s\n", txtname)); + return PyImport_ExecCodeModule(name, text->compiled); +} + +PyObject *blender_import(PyObject *self, PyObject *args) +{ + PyObject *exception, *err, *tb; + char *name; + PyObject *globals = NULL, *locals = NULL, *fromlist = NULL; + PyObject *m; +#ifdef PY_SANDBOXTEST + PyObject *l, *n; +#endif + + if (!PyArg_ParseTuple(args, "s|OOO:bimport", + &name, &globals, &locals, &fromlist)) + return NULL; + +#ifdef PY_SANDBOXTEST + /* check for builtin modules */ + m = PyImport_AddModule("sys"); + l = PyObject_GetAttrString(m, "builtin_module_names"); + n = PyString_FromString(name); + + if (PySequence_Contains(l, n)) { + Py_DECREF(l); + m = PyImport_ImportModuleEx(name, globals, locals, fromlist); + return m; + } else { + /* TODO check for external python toolbox modules */ + + PyErr_Format(PyExc_ImportError, + "Import of external Module %.40s not allowed.\n\ +Please disable security in the UserButtons", name); + Py_DECREF(l); + return NULL; + } + +#else + m = PyImport_ImportModuleEx(name, globals, locals, fromlist); + if (m) + return m; + else + PyErr_Fetch(&exception, &err, &tb); // restore exception for probable later use + + m = importText(name); + if (m) { // found module, ignore above exception + PyErr_Clear(); + Py_XDECREF(exception); Py_XDECREF(err); Py_XDECREF(tb); + printf("imported from text buffer..\n"); + } else { + PyErr_Restore(exception, err, tb); + } + return m; +#endif +} +static PyMethodDef bimport[] = { + { "blimport", blender_import, METH_VARARGS, + "our own import"} +}; + + +/* +PyObject *override_method(PyObject *module, char *methname, PyMethodDef *newcfunc) +{ + PyObject *d; + PyObject *old; + PyObject *pycfunc; + + + d = PyModule_GetDict(module); + old = PyDict_GetItemString(module, methname); + if (!old) + return NULL; + + pycfunc = PyCFunction_New(newcfunc, NULL); + PyDict_SetItemString(d, methname, pycfunc); + + return old; +} +*/ + + +/* this overrides the built in __import__ function +with our customized importer */ +void init_ourImport(void) +{ + PyObject *m, *d; + PyObject *import = PyCFunction_New(bimport, NULL); + + m = PyImport_AddModule("__builtin__"); + d = PyModule_GetDict(m); + PyDict_SetItemString(d, "__import__", import); +} + diff --git a/source/blender/bpython/intern/b_import.h b/source/blender/bpython/intern/b_import.h new file mode 100644 index 00000000000..2bc191942ca --- /dev/null +++ b/source/blender/bpython/intern/b_import.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +/* b_import.c */ +PyObject *importText (char *name); +PyObject *blender_import (PyObject *self, PyObject *args); +void init_ourImport (void); diff --git a/source/blender/bpython/intern/b_interface.c b/source/blender/bpython/intern/b_interface.c new file mode 100644 index 00000000000..ec89680ad91 --- /dev/null +++ b/source/blender/bpython/intern/b_interface.c @@ -0,0 +1,753 @@ +/** Interfacing with Blender + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + * $Id$ + * + * This code is currently messy and an attempt to restructure + * some Blender kernel level code. + * Hopefully a template for a future C-API... + * + * + */ + + +#include "BLI_blenlib.h" // mallocs +#include "BLI_arithb.h" + +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_ipo.h" + +#include "MEM_guardedalloc.h" + +#include "Python.h" +#include "BPY_macros.h" +#include "structmember.h" + +#include "BDR_editobject.h" + +#include "b_interface.h" + +/************************************************************************ + * Generic low level routines + * + */ + +/** This just returns a pointer to the global struct. + * + * Mainly introduced for debugging purposes.. + * + */ + +Global *getGlobal(void) +{ + return &G; +} + +/** define list getters: + These functions return a linked list pointer (ListBase *) from the global + Blender-object list. + + Example: + oblist = getObjectList(); + firstobject = oblist->first; + + */ + +/* +DEF_GETLIST(Scene, scene) +DEF_GETLIST(Object, object) +DEF_GETLIST(Mesh, mesh) +DEF_GETLIST(Camera, camera) +DEF_GETLIST(Material, mat) +DEF_GETLIST(Lamp, lamp) +DEF_GETLIST(World, world) +DEF_GETLIST(Ipo, ipo) +DEF_GETLIST(Image, image) +DEF_GETLIST(Texture, tex) +DEF_GETLIST(Text, text) +DEF_GETLIST(Key, key) +*/ + +/* gets a datablock object from the ID list by name */ +ID *getFromList(ListBase *list, char *name) +{ + ID *id = list->first; + + while (id) { + if(STREQ(name, getIDName(id))) break; + id= id->next; + } + return id; +} + +void printList(ListBase *list) +{ + ID *walk = list->first; + ID *lastwalk = 0; + printf("List: %s\n", walk->name); + while (walk) { + printf(" %s\n", walk->name); + lastwalk = walk; + walk= walk->next; + } + if (list->last != lastwalk) + { + printf("****: listbase->last pointing to wrong end!\n"); + // list->last = lastwalk; + } +} + + +/** (future) garbage collector subroutine */ + + +int gc_mainlist(ListBase *lb) +{ + ID *id = (ID *) lb->first; + + while (id) { + if (getIDUsers(id) == 0) { + switch(GET_ID_TYPE(id)) { + case ID_OB: + BPY_debug(("free [Object %s]\n", getIDName(id))); + unlink_object((Object *) id); + free_libblock(lb, id); + break; + default: break; + } + } + id = id->next; + } + return 1; +} + + /** Garbage collection function. EXPERIMENTAL! + * This should free Blender from all unreferenced Objects (i.e. + * user count == 0). + * Don't expect too much yet -- User counting isn't done + * consequently in Blender. Neither parenting or bevelcurves + * etc. respect user counts...therefore, no circular references + * show up -- which are in fact possible; example: + * + * A BevelCurve is parenting its BevelObject: so there is a + * reference from the BevelObject to the BevelCurve, and a + * reference back from the Bevelcurve to the BevelObject. + * + * There are a lot of cleanup functions in Blender taking care + * of updating (invalidating) references to deleted objects. + * See unlink_object() for more details. + * + * This function must not be called inside a script, so don't go + * and create a wrapper for it :-) + * In a hopefully later implementation, the Python garbage collection + * might be used. For the moment, this is better than 'Save and Reload' + */ + + int garbage_collect(Main *m) + { + /* Remember, all descriptor objects must BOB_DECUSER on their raw + Blender Datablock in their __del__ method (C-API: dealloc function) */ + + gc_mainlist(&m->object); + + /* TODO proper kernel level functions for safely freeing these objects + * must first be implemented... + gc_mainlist(&m->mesh); + gc_mainlist(&m->mat); + gc_mainlist(&m->lamp); + gc_mainlist(&m->camera); + + .. and this list is far from being complete. + */ + + return 1; +} + +/** expands pointer array of length 'oldsize' to length 'newsize'. + * A pointer to the (void *) array must be passed as first argument + * The array pointer content can be NULL, in this case a new array of length + * 'newsize' is created. + */ + +static int expandPtrArray(void **p, int oldsize, int newsize) +{ + void *newarray; + + if (newsize < oldsize) { + return 0; + } + newarray = MEM_callocN(newsize * sizeof(void *), "PtrArray"); + if (*p) { + memcpy(newarray, *p, oldsize); + MEM_freeN(*p); + } + *p = newarray; + return 1; +} + +/************************************************************************ + * Material object low level routines + * + */ + +/* MAXMAT = maximum number of materials per object/ object data */ + +#define MATINDEX_CHECK(x) \ + if ((x) < 0 || (x) >= MAXMAT) { printf("illegal matindex!\n"); return 0; } + +/** Returns a new material list (material pointer array) of length 'len' + * + */ + +Material **newMaterialList(int len) +{ + Material **matlist = + (Material **) MEM_mallocN(len * sizeof(Material *), "MaterialList"); + return matlist; +} + +/** releases material list and decrements user count on materials */ + +int releaseMaterialList(Material **matlist, int len) +{ + int i; + Material *m; + + MATINDEX_CHECK(len); + + for (i= 0; i < len; i++) { + + m = matlist[i]; + BOB_XDECUSER((ID *) m); + } + MEM_freeN(matlist); + return 1; +} + +/** Synchronizes Object <-> data material lists. Blender just wants it. */ + +int synchronizeMaterialLists(Object *object, void *data) +{ + // get pointer to data's material array: + // and number of data materials + // ... because they will need modification. + + Material ***p_dataMaterials = give_matarar(object); + short *nmaterials = give_totcolp(object); + + if (object->totcol > *nmaterials){ // more object mats than data mats + *nmaterials = object->totcol; + return expandPtrArray((void *) p_dataMaterials, *nmaterials, object->totcol); + } else if (object->totcol < *nmaterials) { + object->totcol = *nmaterials; + return expandPtrArray((void *) &object->mat, object->totcol, *nmaterials); + } + return 1; // in this case, no synchronization needed; they're of equal + // length +} + +/************************************************************************ + * Object low level routines + * + */ + +/** creates a new empty object of type OB_ (TODO: should be enum) + * + */ + + +Object *object_new(int type) +{ + Object *object; + char name[32]; + + Global *g = getGlobal(); + + switch(type) { + case OB_MESH: strcpy(name, "Mesh"); break; + case OB_CURVE: strcpy(name, "Curve"); break; + case OB_SURF: strcpy(name, "Surf"); break; + case OB_FONT: strcpy(name, "Text"); break; + case OB_MBALL: strcpy(name, "Mball"); break; + case OB_CAMERA: strcpy(name, "Camera"); break; + case OB_LAMP: strcpy(name, "Lamp"); break; + case OB_IKA: strcpy(name, "Ika"); break; + case OB_LATTICE: strcpy(name, "Lattice"); break; + case OB_WAVE: strcpy(name, "Wave"); break; + case OB_ARMATURE: strcpy(name,"Armature");break; + default: strcpy(name, "Empty"); + } + + object = alloc_libblock(getObjectList(), ID_OB, name); + + /* user count is set to 1 by alloc_libblock, we just reset it to 0... */ + BOB_USERCOUNT((ID*) object) = 0; // it's a new object, so no user yet + object->flag = 0; + object->type = type; + + /* transforms */ + QuatOne(object->quat); + QuatOne(object->dquat); + + object->col[3]= 1.0; // alpha + + object->size[0] = object->size[1] = object->size[2] = 1.0; + object->loc[0] = object->loc[1] = object->loc[2] = 0.0; + Mat4One(object->parentinv); + Mat4One(object->obmat); + object->dt = OB_SHADED; // drawtype + + object_setdefaults(object); + + object->lay = 1; // Layer, by default visible + + switch(type) { + case OB_MESH: object->data= add_mesh(); g->totmesh++; break; + case OB_CAMERA: object->data= add_camera(); break; + case OB_LAMP: object->data= add_lamp(); g->totlamp++; break; + + // TODO the following types will be supported later + // case OB_CURVE: object->data= add_curve(OB_CURVE); g->totcurve++; break; + // case OB_SURF: object->data= add_curve(OB_SURF); g->totcurve++; break; + // case OB_FONT: object->data= add_curve(OB_FONT); break; + // case OB_MBALL: object->data= add_mball(); break; + // case OB_IKA: object->data= add_ika(); object->dt= OB_WIRE; break; + // case OB_LATTICE: object->data= (void *)add_lattice(); object->dt= OB_WIRE; break; + // case OB_WAVE: object->data= add_wave(); break; + // case OB_ARMATURE: object->data=add_armature();break; + } + + g->totobj++; // gee, I *hate* G + return object; +} + +/* returns new Base */ +Base *object_newBase(Object *object) +{ + Base *base; + base = MEM_callocN(sizeof(Base), "newbase"); + if (!base) + return 0; + base->object = object; + base->lay = object->lay; + base->flag = object->flag; + return base; +} + +Object *object_copy(Object *object) +{ + Object *new; + + new = copy_object(object); + BOB_USERCOUNT((ID*) new) = 0; // it's a new object, so no user yet + return new; +} + +/* Set draw mode of object */ +void object_setDrawMode(Object *object, int modebits) +{ + object->dt = (modebits & 0xff); + object->dtx = (modebits >> 8); +} + +int object_getDrawMode(Object *object) +{ + return (((int) object->dtx) << 8 ) + object->dt; +} + +/* link data to Object object */ +int object_linkdata(Object *object, void *data) +{ + ID *oldid, *id; + int valid; + + if (!data) return 0; + + oldid = (ID*) object->data; + id = (ID*) data; + + valid = 0; + +#define _CASE(objtype, idtype) \ + case objtype:\ + if (GET_ID_TYPE(id) == idtype) \ + valid = 1; \ + break; + + switch (object->type) { + _CASE(OB_MESH, ID_ME) + _CASE(OB_CAMERA, ID_CA) + _CASE(OB_LAMP, ID_LA) + default: // not supported + return 0; + } + if (valid) { + object->data = data; + BOB_INCUSER(id); + if (oldid) + BOB_DECUSER(oldid); // dec users + + // extra check for multi materials on meshes: + // This is a hack to check whether object material lists are of same + // length as their data material lists.. + //if (GET_ID_TYPE(id) == ID_ME) { + //test_object_materials(id); + //} + return 1; + } + return 0; +} + +/* release data from object object */ + +int object_unlinkdata(Object *object) +{ + ID *id = object->data; + + BOB_XDECUSER(id); + return 1; +} + +/** set Object materials: + * takes a list of Material pointers of maximum length MAXMAT + */ + +int object_setMaterials(Object *object, Material **matlist, int len) +{ + int i; + + MATINDEX_CHECK(len) + if (object->mat) { + releaseMaterialList(object->mat, len); + } + // inc user count on all materials + for (i = 0; i < len; i++) { + BOB_XINCUSER( (ID *) matlist[i]); + } + + object->mat = matlist; + object->totcol = len; + object->actcol = len - 1; // XXX + // workaround: blender wants the object's data material list + // to be of the same length, otherwise colourful fun happens. + // so, we synchronize this here: + + switch (object->type) + { + case OB_MESH: + case OB_CURVE: + case OB_FONT: + case OB_SURF: + case OB_MBALL: + synchronizeMaterialLists(object, object->data); + break; + default: + return 0; + } + return 1; +} + +/** make 'object' the parent of the object 'child' + * + * mode = 1: set parent inverse matrix to _1_ ('clear inverse') + * fast = 1: Don't update scene base (hierarchy). In this case, + * sort_baselist() needs to be called explicitely before redraw. + */ + +int object_makeParent(Object *parent, Object *child, int mode, int fast) +{ + if (test_parent_loop(parent, child)) { + PyErr_SetString(PyExc_RuntimeError, "parenting loop detected!"); + return 0; + } + child->partype = PAROBJECT; + child->parent = parent; + if (mode == 1) { + Mat4One(child->parentinv); // parent inverse = unity + child->loc[0] = 0.0; child->loc[1] = 0.0; child->loc[2] = 0.0; + } else { + what_does_parent(child); + Mat4Invert(child->parentinv, parent->obmat); // save inverse + } + + /* This is some bad global thing again -- we should determine + the current scene + another way. Later. */ + if (!fast) + sort_baselist(getGlobal()->scene); + + return 1; +} + +/** Unlink parenting hierarchy: + * + * mode = 2: keep transform + * fast = 1: don't update scene bases. see makeParent() + */ + +int object_clrParent(Object *child, int mode, int fast) +{ + Object *par; + + par = child->parent; + child->parent = 0; + if (mode == 2) { // keep transform + apply_obmat(child); + } + if (!fast) + sort_baselist(getGlobal()->scene); + return 1; +} + +/** Set object's defaults */ + +int object_setdefaults(Object *ob) +{ + if(U.flag & MAT_ON_OB) ob->colbits= -1; + switch(ob->type) { + case OB_CAMERA: + case OB_LAMP: + ob->trackflag = OB_NEGZ; + ob->upflag = OB_POSY; + break; + default: + ob->trackflag = OB_POSY; + ob->upflag = OB_POSZ; + } + ob->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT; + + /* duplivert settings */ + + ob->dupon = 1; ob->dupoff = 0; + ob->dupsta = 1; ob->dupend = 100; + + /* Gameengine defaults*/ + ob->mass= ob->inertia= 1.0; + ob->formfactor= 0.4; + ob->damping= 0.04; + ob->rdamping= 0.1; + ob->anisotropicFriction[0] = 1.0; + ob->anisotropicFriction[1] = 1.0; + ob->anisotropicFriction[2] = 1.0; + + /* default to not use fh in new system */ + ob->gameflag= OB_PROP; /*|OB_DO_FH; */ + + return 1; +} + +/************************************************************************ + * Creation of new data blocks + * + * We [ab|re]use the blender kernel functions, but set the user count to 0, + * because the object does not have users yet. + * Currently, the user count is abused as reference count which should be + * separate in future + */ + +Material *material_new(void) +{ + Material *m = add_material("Material"); + BOB_USERCOUNT((ID*) m) = 0; // set 'refcount' to 0, because + // it's a free material + return m; +} + +Lamp *lamp_new() +{ + Lamp *la; + + la = add_lamp(); + BOB_USERCOUNT((ID*) la) = 0; + + return la; +} + +Camera *camera_new() +{ + Camera *cam; + + cam = add_camera(); + BOB_USERCOUNT((ID*) cam) = 0; + return cam; +} + +Ipo *ipo_new(int type, char *name) +{ + Ipo *ipo; + + ipo = add_ipo(name, type); + BOB_USERCOUNT((ID*) ipo) = 0; + return ipo; +} + + +/* Finds the ipo curve with channel code 'code' in the datablock 'ipo' + and returns it, if found (NULL otherwise) */ + +IpoCurve *ipo_findcurve(Ipo *ipo, int code) +{ + IpoCurve *ipocurve; + + ipocurve = ipo->curve.first; + while(ipocurve) { + if (ipocurve->adrcode == code) break; + ipocurve = ipocurve->next; + } + return ipocurve; +} + + +/** Returns a new Ipo curve */ +IpoCurve *ipocurve_new() +{ + IpoCurve *curve; + + curve = MEM_callocN(sizeof(IpoCurve), "new_ipocurve"); + curve->flag = IPO_VISIBLE; + return curve; +} + +IpoCurve *ipocurve_copy(IpoCurve *curve) +{ + IpoCurve *newcurve; + + newcurve = MEM_callocN(sizeof(IpoCurve), "new_ipocurve"); + memcpy(newcurve, curve, sizeof(IpoCurve)); + // copy bez triples: + newcurve->bezt= MEM_mallocN(curve->totvert*sizeof(BezTriple), "ipocurve_copy"); + memcpy(newcurve->bezt, curve->bezt, curve->totvert*sizeof(BezTriple)); + return newcurve; +} + +/** Assign ipo to object object */ + +/* macros, see b_interface.h */ + +DEF_ASSIGN_IPO(object, Object) // defines object_assignIpo() + +DEF_ASSIGN_IPO(camera, Camera) + +DEF_ASSIGN_IPO(lamp, Lamp) + +DEF_ASSIGN_IPO(material, Material) + +/************************************************************************ + * Mesh object low level routines + * + */ + +/** Returns a new, free (non owned) mesh. + * add_mesh() automatically returns a mesh object with users = 1, + * so we set it to 0. Hack, hack. + */ + +Mesh *mesh_new(void) +{ + Mesh *me = add_mesh(); + ((ID *) me)->us = 0; + return me; +} + +/** updates drawing properties etc. of mesh */ + +void mesh_update(Mesh *mesh) +{ + edge_drawflags_mesh(mesh); + tex_space_mesh(mesh); +} + +/************************************************************************ + * Scene object low level routines + * + */ + +/** Returns current Scene */ + +Scene *scene_getCurrent(void) +{ + return getGlobal()->scene; +} + +/* returns base of object 'object' in Scene 'scene', 0 if nonexistant + * A base is basically an visual instantiation of an 3D object (Object) + * in a Scene. See scene_linkObject() + * + */ + +Base *scene_getObjectBase(Scene *scene, Object *object) +{ + Base *base; + base = scene->base.first; + while (base) + { + if (object == base->object) // it exists + return base; + base = base->next; + } + return NULL; +} + +/* links an object into a scene */ +int scene_linkObject(Scene *scene, Object *object) +{ + Base *base, *b; + b = scene_getObjectBase(scene, object); + if (b) + return 0; + base = object_newBase(object); + if (!base) { + return 0; + } + BOB_INCUSER((ID *) object); // incref the object + BLI_addhead(&scene->base, base); + return 1; +} + +/* unlinks an object from a scene */ +int scene_unlinkObject(Scene *scene, Object *object) +{ + Base *base; + base = scene_getObjectBase(scene, object); + if (base) { + BLI_remlink(&scene->base, base); + BOB_DECUSER((ID *) object); + MEM_freeN(base); + scene->basact = 0; // make sure the just deleted object has no longer an + // active base (which happens if it was selected + return 1; + } + else return 0; +} + diff --git a/source/blender/bpython/intern/b_interface.h b/source/blender/bpython/intern/b_interface.h new file mode 100644 index 00000000000..b2af2280f1f --- /dev/null +++ b/source/blender/bpython/intern/b_interface.h @@ -0,0 +1,184 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include "DNA_ID.h" +#include "DNA_mesh_types.h" +#include "DNA_view3d_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_text_types.h" +#include "DNA_curve_types.h" +#include "DNA_screen_types.h" +#include "DNA_camera_types.h" +#include "DNA_ipo_types.h" +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_scriptlink_types.h" +#include "DNA_userdef_types.h" /* for userdata struct; U.pythondir */ + +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_scene.h" +#include "BKE_global.h" + +/* DEFINES */ + +#define ASSIGN_IPO(prefix, type) \ + prefix##_assignIpo(type *obj, Ipo *ipo) + +// example DEF_ASSIGN_IPO(Object, obj) -> +// int object_assignIpo(Object *obj, Ipo *ipo) + +#define DEF_ASSIGN_IPO(prefix, type) \ + int prefix##_assignIpo(type *obj, Ipo *ipo) \ + { \ + BOB_XDECUSER((ID*) obj->ipo); \ + BOB_XINCUSER((ID*) ipo); \ + obj->ipo = ipo; \ + return 1; \ + } \ + +// defined prototypes: + +#define FUNC_ASSIGN_IPO(prefix, arg1, arg2) \ + prefix##_assignIpo(arg1, arg2) + +#define object_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(object, arg1, arg2) +#define material_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(material, arg1, arg2) +#define camera_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(camera, arg1, arg2) +#define lamp_assignIpo(arg1, arg2) FUNC_ASSIGN_IPO(lamp, arg1, arg2) + +/** Defines for List getters */ + +/* +#define PROTO_GETLIST(name, member) \ + ListBase *get##name##List(void) + +#define DEF_GETLIST(name, member) \ + PROTO_GETLIST(name, member) \ + { \ + return &(G.main->member); \ + } +*/ + +/* PROTOS */ + +#define _GETMAINLIST(x) \ + (&(G.main->x)) + +#define getSceneList() _GETMAINLIST(scene) +#define getObjectList() _GETMAINLIST(object) +#define getMeshList() _GETMAINLIST(mesh) +#define getMaterialList() _GETMAINLIST(mat) +#define getCameraList() _GETMAINLIST(camera) +#define getLampList() _GETMAINLIST(lamp) +#define getWorldList() _GETMAINLIST(world) +#define getIpoList() _GETMAINLIST(ipo) +#define getImageList() _GETMAINLIST(image) +#define getTextureList() _GETMAINLIST(tex) +#define getTextList() _GETMAINLIST(text) +#define getKeyList() _GETMAINLIST(key) +#define getLatticeList() _GETMAINLIST(latt) + +/* +PROTO_GETLIST(Scene, scene); +PROTO_GETLIST(Object, object); +PROTO_GETLIST(Mesh, mesh); +PROTO_GETLIST(Camera, camera); +PROTO_GETLIST(Material, mat); +PROTO_GETLIST(Lamp, lamp); +PROTO_GETLIST(World, world); +PROTO_GETLIST(Ipo, ipo); +PROTO_GETLIST(Image, image); +PROTO_GETLIST(Texture, tex); +PROTO_GETLIST(Text, text); +PROTO_GETLIST(Key, key); */ + + +Global *getGlobal(void); // get Global struct + +ID *getFromList(ListBase *list, char *name); + +int garbage_collect(Main *m); + + +Material **newMaterialList(int len); +int releaseMaterialList(struct Material **matlist, int len); +int synchronizeMaterialLists(Object *object, void *data); + +// Datablock management + +Material *material_new(void); +int material_assignIpo(Material *, Ipo *); + +Lamp *lamp_new(void); +int lamp_assignIpo(Lamp *, Ipo *); + +Camera *camera_new(void); +int camera_assignIpo(Camera *, Ipo *); + +Ipo *ipo_new(int type, char *name); +IpoCurve *ipo_findcurve(Ipo *ipo, int code); +IpoCurve *ipocurve_new(void); +IpoCurve *ipocurve_copy(IpoCurve *curve); + +// Object management +Base *object_newBase(Object *obj); +int object_linkdata(Object *obj, void *data); +int object_unlinkdata(Object *obj); +int object_setMaterials(Object *object, Material **matlist, int len); +int object_setdefaults(Object *ob); +int object_copyMaterialsTo(Object *object, Material **matlist, int len); +int object_makeParent(Object *parent, Object *child, int noninverse, int fast); +int object_clrParent(Object *child, int mode, int fast); +Object *object_new(int type); +Object *object_copy(Object *obj); +void object_setDrawMode(Object *object, int val); +int object_getDrawMode(Object *object); + +int object_assignIpo(Object *, Ipo *); + +Scene *scene_getCurrent(void); +int scene_linkObject(Scene *scene, Object *obj); +int scene_unlinkObject(Scene *scene, Object *object); +Base *scene_getObjectBase(Scene *scene, Object *object); + +Mesh *mesh_new(void); +void mesh_update(Mesh *me); + +/* blender's program name */ +extern char bprogname[]; /* init in creator.c */ + + + diff --git a/source/blender/bpython/intern/opy_blender.c b/source/blender/bpython/intern/opy_blender.c new file mode 100644 index 00000000000..6bbac3d958e --- /dev/null +++ b/source/blender/bpython/intern/opy_blender.c @@ -0,0 +1,342 @@ +/* python code for Blender, written by Daniel Dunbar */ +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" + +#include "BPY_macros.h" +#include "b_interface.h" +#include "BPY_tools.h" +#include "BPY_modules.h" +#include "BPY_main.h" + +#include "BKE_main.h" +#include "BKE_object.h" // during_script() (what is this ?) +#include "BKE_global.h" +#include "BKE_ipo.h" // frame_to_float() +#include "BKE_blender.h" + +#include "BIF_space.h" // allqueue() +#include "BSE_headerbuttons.h" + +#include "BPY_types.h" // userdefined Python Objects +#include <string.h> + +#include "DNA_userdef_types.h" + +#include "mydevice.h" + +//#include "py_blender.h" +//#include "screen.h" +//#include "ipo.h" + +void INITMODULE(BLENDERMODULE)(void); + +PyObject *g_sysmodule; + + +/* +NamedEnum TextureTypes[]= { + {"Clouds", TEX_CLOUDS}, + {"Wood", TEX_WOOD}, + {"Marble", TEX_MARBLE}, + {"Magic", TEX_MAGIC}, + {"Blend", TEX_BLEND}, + {"Stucci", TEX_STUCCI}, + {"Noise", TEX_NOISE}, + {"Image", TEX_IMAGE}, + {"Plugin", TEX_PLUGIN}, + {"Envmap", TEX_ENVMAP}, + {NULL} +}; + +DataBlockProperty Texture_Properties[]= { + DBP_NamedEnum("type", "type", TextureTypes), + DBP_Short("stype", "stype", 0.0, 0.0, 0), + + DBP_Float("noisesize", "noisesize", 0.0, 0.0, 0), + DBP_Float("turbulence", "turbul", 0.0, 0.0, 0), + DBP_Float("brightness", "bright", 0.0, 0.0, 0), + DBP_Float("contrast", "contrast", 0.0, 0.0, 0), + DBP_Float("rfac", "rfac", 0.0, 0.0, 0), + DBP_Float("gfac", "gfac", 0.0, 0.0, 0), + DBP_Float("bfac", "bfac", 0.0, 0.0, 0), + DBP_Float("filtersize", "filtersize", 0.0, 0.0, 0), + + DBP_Short("noisedepth", "noisedepth", 0.0, 0.0, 0), + DBP_Short("noisetype", "noisetype", 0.0, 0.0, 0), + + {NULL} +}; +*/ + + +/*****************************/ +/* Main interface routines */ +/*****************************/ + + +#define BP_CURFRAME 1 +#define BP_CURTIME 2 +#define BP_FILENAME 3 + +static char Blender_Set_doc[]= +"(request, data) - Update settings in Blender\n\ +\n\ +(request) A string indentifying the setting to change\n\ + 'curframe' - Sets the current frame using the number in data"; + +static PyObject *Blender_Set (PyObject *self, PyObject *args) +{ + char *name; + PyObject *arg; + + BPY_TRY(PyArg_ParseTuple(args, "sO", &name, &arg)); + + if (STREQ(name, "curframe")) { + int framenum; + + BPY_TRY(PyArg_Parse(arg, "i", &framenum)); + + (G.scene->r.cfra)= framenum; + + update_for_newframe(); + + } else { + return BPY_err_ret_ob(PyExc_AttributeError, "bad request identifier"); + } + + return BPY_incr_ret(Py_None); +} + +static char Blender_Get_doc[]= +"(request) - Retrieve settings from Blender\n\ +\n\ +(request) A string indentifying the data to be returned\n\ + 'curframe' - Returns the current animation frame\n\ + 'curtime' - Returns the current animation time\n\ + 'staframe' - Returns the start frame of the animation\n\ + 'endframe' - Returns the end frame of the animation\n\ + 'filename' - Returns the name of the last file read or written\n\ + 'version' - Returns the Blender version number"; + +static PyObject *Blender_Get (PyObject *self, PyObject *args) +{ + PyObject *ob; + PyObject *dict; + + BPY_TRY(PyArg_ParseTuple(args, "O", &ob)); + + if (PyString_Check(ob)) { + char *str= PyString_AsString(ob); + + if (STREQ(str, "curframe")) + return PyInt_FromLong((G.scene->r.cfra)); + + else if (STREQ(str, "curtime")) + return PyFloat_FromDouble(frame_to_float((G.scene->r.cfra))); + + else if (STREQ(str, "staframe")) + return PyInt_FromLong((G.scene->r.sfra)); + + else if (STREQ(str, "endframe")) + return PyInt_FromLong((G.scene->r.efra)); + + else if (STREQ(str, "filename")) + return PyString_FromString(getGlobal()->sce); + + else if (STREQ(str, "vrmloptions")) // TODO: quick hack, clean up! + { + dict= PyDict_New(); + PyDict_SetItemString(dict, "twoside", + PyInt_FromLong(U.vrmlflag & USERDEF_VRML_TWOSIDED)); + PyDict_SetItemString(dict, "layers", + PyInt_FromLong(U.vrmlflag & USERDEF_VRML_LAYERS)); + PyDict_SetItemString(dict, "autoscale", + PyInt_FromLong(U.vrmlflag & USERDEF_VRML_AUTOSCALE)); + return dict; + } + else if (STREQ(str, "version")) + return PyInt_FromLong(G.version); + } else { + return BPY_err_ret_ob(PyExc_AttributeError, "expected string argument"); + } + + return BPY_err_ret_ob(PyExc_AttributeError, "bad request identifier"); +} + +/* for compatibility: <<EOT */ + +static char Blender_Redraw_doc[]= "() - Redraw all 3D windows"; + +static PyObject *Blender_Redraw(PyObject *self, PyObject *args) +{ + int wintype = SPACE_VIEW3D; + + BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype)); + + return Windowmodule_Redraw(self, Py_BuildValue("(i)", wintype)); +} +/* EOT */ + +#undef MethodDef +#define MethodDef(func) {#func, Blender_##func, METH_VARARGS, Blender_##func##_doc} + +static struct PyMethodDef Blender_methods[] = { + MethodDef(Redraw), + MethodDef(Get), + MethodDef(Set), + {NULL, NULL} +}; + +struct PyMethodDef Null_methods[] = { + {NULL, NULL} +}; + + +static char Blender_Const_doc[] = +"This module is only there for compatibility reasons.\n\ +It will disappear in future, please use the Blender.Get() syntax instead\n"; + + +/* Blender system module + Sorry, this is a mess, but had to be hacked in in order to meet deadlines.. + TODO: Cleanup +*/ + +static char sys_dirname_doc[] = + "(path) - returns the directory name of 'path'"; + +static PyObject *sys_dirname(PyObject *self, PyObject *args) +{ + PyObject *c; + + char *name, dirname[256]; + char sep; + int n; + + BPY_TRY(PyArg_ParseTuple(args, "s", &name)); + + c = PyObject_GetAttrString(g_sysmodule, "dirsep"); + sep = PyString_AsString(c)[0]; + Py_DECREF(c); + + n = strrchr(name, sep) - name; + if (n > 255) { + PyErr_SetString(PyExc_RuntimeError, "path too long"); + return 0; + } + strncpy(dirname, name, n); + dirname[n] = 0; + + return Py_BuildValue("s", dirname); +} + +#define METHODDEF(func) {#func, sys_##func, METH_VARARGS, sys_##func##_doc} + +static struct PyMethodDef sys_methods[] = { + METHODDEF(dirname), + {NULL, NULL} +}; + + +PyObject *init_sys(void) +{ + + PyObject *m, *dict, *p; + + m = Py_InitModule(SUBMODULE(sys), sys_methods); + g_sysmodule = m; + + dict= PyModule_GetDict(m); + +#ifdef WIN32 + p = Py_BuildValue("s", "\\"); +#else + p = Py_BuildValue("s", "/"); +#endif + + PyDict_SetItemString(dict, "dirsep" , p); + return m; +} + +/* ----------------------------------------------------------------- */ + +void INITMODULE(BLENDERMODULE)(void) +{ + PyObject *m, *dict, *d; + + m = Py_InitModule4(MODNAME(BLENDERMODULE), Blender_methods, (char*) 0, (PyObject*)NULL, PYTHON_API_VERSION); + + DataBlock_Type.ob_type = &PyType_Type; + + + init_py_vector(); + init_py_matrix(); + + dict = PyModule_GetDict(m); + g_blenderdict = dict; + + /* pyblender data type initialization */ + init_types(dict); + init_Datablockmodules(dict); + + /* kept for compatibility...will be removed XXX */ + PyDict_SetItemString(dict, "bylink", PyInt_FromLong(0)); + PyDict_SetItemString(dict, "link", Py_None); + + /* initialize submodules */ + PyDict_SetItemString(dict, "sys", init_sys()); + Py_INCREF(Py_None); + PyDict_SetItemString(dict, "Image", INITMODULE(Image)()); + PyDict_SetItemString(dict, "Window",INITMODULE(Window)()); + PyDict_SetItemString(dict, "NMesh", init_py_nmesh()); + PyDict_SetItemString(dict, "Draw", init_py_draw()); + PyDict_SetItemString(dict, "BGL", init_py_bgl()); +#ifdef EXPERIMENTAL + PyDict_SetItemString(dict, "Nurbs", init_py_nurbs()); +#endif + /* CONSTANTS */ + + /* emulate old python XXX -> should go to Blender/ python externals */ + + m = Py_InitModule4(MODNAME(BLENDERMODULE) ".Const" , Null_methods, Blender_Const_doc, (PyObject*)NULL, PYTHON_API_VERSION); + d = PyModule_GetDict(m); + PyDict_SetItemString(dict, "Const", m); + PyDict_SetItemString(d, "BP_CURFRAME", PyInt_FromLong(BP_CURFRAME)); + PyDict_SetItemString(d, "BP_CURTIME", PyInt_FromLong(BP_CURTIME)); + + PyDict_SetItemString(d, "CURFRAME", PyInt_FromLong(BP_CURFRAME)); + PyDict_SetItemString(d, "CURTIME", PyInt_FromLong(BP_CURTIME)); + PyDict_SetItemString(d, "FILENAME", PyInt_FromLong(BP_FILENAME)); +} + diff --git a/source/blender/bpython/intern/opy_datablock.c b/source/blender/bpython/intern/opy_datablock.c new file mode 100644 index 00000000000..6804c834897 --- /dev/null +++ b/source/blender/bpython/intern/opy_datablock.c @@ -0,0 +1,1299 @@ +/* Datablock handling code. This handles the generic low level access to Blender + Datablocks. */ + +/* + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/************************************************************************** + * This code provides low level, generalized access to the Blender Datablock + * objects. It basically creates a descriptor Python Object of type 'DataBlock' + * for each requested Blender datablock. + * This introduces the question of synchronization, for example: + * What happens if an Object is deleted? + * + * Blender Objects have their own 'reference counting', e.g. a Mesh datablock + * used by two Objects has a user count of 2. Datablocks with user count of 0 + * are not saved to Disk -- this is the current way Blender does + * 'garbage collection' + * Therefore, an object should normally not be deleted by Python, but rather + * unlinked from its parent object. + * Still, for other objects like Scene or Text objects, deletion from 'Main' + * is desired. + * The current workaround: + + * Some objects can be explicitely deleted (not recommended, but possible) -- + * they have a user count of 1, even if they are used by objects in some way, + * for example Text objects which are used by any other Blender object + * through a ScriptLink. + * + * Objects that are deleted through Python end up with a 'dead' descriptor; + * accessing the descriptor after deletion causes a Python exception. + * + * NASTY UGLY DIRTY, VUILE, DRECKIGES AND STILL REMAINING PROBLEM: + * + * It is (in the current API) possible to construct the case, that an + * Object is deleted in Blender, but the Python descriptor does not know + * about this. Accessing the descriptor (which simply contains a pointer to + * the raw datablock struct) will most probably end in colourful joy. + * + * TODO: + * possible solutions: + * - rewrite datablock handling that way, that the descriptor uses an id + * tag to retrieve that pointer through a getPointerbyID() function + * (if the object exists!) on each access. Slow. + * - make sure that deletion always happends by the descriptor and never + * delete the raw datastructure. This solution would imply a major + * redesign of user action handling (GUI actions calling python). + * Not likely to happen...better fusion raw and python object in this case. + * After all, still somewhat dirty. + * - make sure that no deletion can happen in Blender while a script + * still accesses the raw data - i.e. implement user counting of raw + * objects with descriptors. This would need an implementation of + * garbage collection in Blender. This might sound like the most feasible + * solution... + */ + + +#include "Python.h" +#include "BPY_macros.h" + +#include "opy_datablock.h" +#include "opy_nmesh.h" + +#include "opy_vector.h" /* matrix datatypes */ + +#include "BPY_tools.h" +#include "BPY_types.h" +#include "BPY_main.h" + +#include "MEM_guardedalloc.h" + +#include "b_interface.h" /* needed for most of the DNA datatypes */ + + +/* ---------------------------------------------------------------------- */ + +/*********************/ +/* Camera Datablocks */ + +DATABLOCK_GET(Cameramodule, camera, getCameraList()) + +static char Cameramodule_New_doc[] = +"() - returns new Camera object"; + +PyObject *Cameramodule_New (PyObject *self, PyObject *args) +{ + Camera *obj; + obj = camera_new(); + return DataBlock_fromData(obj); +} + +#ifdef FUTURE_PYTHON_API + +DataBlockProperty Camera_Properties[]= { + {"lens", "lens", DBP_TYPE_FLO, 0, 1.0, 250.0}, + {"clipStart","clipsta", DBP_TYPE_FLO, 0, 0.0, 100.0}, + {"clipEnd", "clipend", DBP_TYPE_FLO, 0, 1.0, 5000.0}, + {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"mode", "flag", DBP_TYPE_SHO, 0, 0.0, 0.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#else + +DataBlockProperty Camera_Properties[]= { + {"Lens", "lens", DBP_TYPE_FLO, 0, 1.0, 250.0}, + {"ClSta", "clipsta", DBP_TYPE_FLO, 0, 0.0, 100.0}, + {"ClEnd", "clipend", DBP_TYPE_FLO, 0, 1.0, 5000.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#endif + +static struct PyMethodDef Cameramodule_methods[] = { + {"New", Cameramodule_New, METH_VARARGS, Cameramodule_New_doc}, + {"get", Cameramodule_get, METH_VARARGS, Cameramodule_get_doc}, + {NULL, NULL} +}; + +DATABLOCK_ASSIGN_IPO(Camera, camera) // defines Camera_assignIpo + +static struct PyMethodDef Camera_methods[] = { + {"clrIpo", Camera_clrIpo, METH_VARARGS, Camera_clrIpo_doc}, + {"assignIpo", Camera_assignIpo, METH_VARARGS, Camera_assignIpo_doc}, + {NULL, NULL} +}; + +/***********************/ +/* Material Datablocks */ + + +/** returns a pointer to a new (malloced) material list created from + * a Python material list + */ + +Material **newMaterialList_fromPyList(PyObject *list) +{ + int i, len; + DataBlock *block = 0; + Material *mat; + Material **matlist; + + len = PySequence_Length(list); + if (len > 16) len = 16; + + matlist = newMaterialList(len); + + for (i= 0; i < len; i++) { + + block= (DataBlock *) PySequence_GetItem(list, i); + + if (DataBlock_isType(block, ID_MA)) { + mat = (Material *) block->data; + matlist[i] = mat; + } else { + // error; illegal type in material list + Py_DECREF(block); + MEM_freeN(matlist); + return NULL; + } + Py_DECREF(block); + } + return matlist; +} + +/** Return Python List from material pointer list 'matlist' with length + * 'len' + * + */ + +PyObject *PyList_fromMaterialList(Material **matlist, int len) +{ + PyObject *list; + int i; + + list = PyList_New(0); + if (!matlist) return list; + + for (i = 0; i < len; i++) { + Material *mat= matlist[i]; + PyObject *ob; + + if (mat) { + ob = DataBlock_fromData(mat); + PyList_Append(list, ob); + Py_DECREF(ob); // because Append increfs! + } + } + return list; +} + +DATABLOCK_GET(Materialmodule, material, getMaterialList()) + +DATABLOCK_NEW(Materialmodule, Material, material_new()) + +static struct PyMethodDef Materialmodule_methods[] = { + {"get", Materialmodule_get, METH_VARARGS, Materialmodule_get_doc}, + {"New", Materialmodule_New, METH_VARARGS, Materialmodule_New_doc}, + {NULL, NULL} +}; + +DATABLOCK_ASSIGN_IPO(Material, material) + +static struct PyMethodDef Material_methods[] = { + {"clrIpo", Material_clrIpo, METH_VARARGS, Material_clrIpo_doc}, + {"assignIpo", Material_assignIpo, METH_VARARGS, Material_assignIpo_doc}, + {NULL, NULL} +}; + +#ifdef FUTURE_PYTHON_API + +DataBlockProperty Material_Properties[]= { + {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"specR", "specr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"specG", "specg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"specB", "specb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"mirR", "mirr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"mirG", "mirg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"mirB", "mirb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ref", "ref", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"alpha", "alpha", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"emit", "emit", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"amb", "amb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"spec", "spec", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"specTransp", "spectra", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"haloSize", "hasize", DBP_TYPE_FLO, 0, 0.0, 10000.0}, + + {"mode", "mode", DBP_TYPE_INT, 0, 0.0, 0.0}, + {"hard", "har", DBP_TYPE_SHO, 0, 1.0, 128.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#else + +DataBlockProperty Material_Properties[]= { + {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"SpecR", "specr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"SpecG", "specg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"SpecB", "specb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"MirR", "mirr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"MirG", "mirg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"MirB", "mirb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Ref", "ref", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Alpha", "alpha", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Emit", "emit", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Amb", "amb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Spec", "spec", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"SpTra", "spectra", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"HaSize", "hasize", DBP_TYPE_FLO, 0, 0.0, 10000.0}, + + {"Mode", "mode", DBP_TYPE_INT, 0, 0.0, 0.0}, + {"Hard", "har", DBP_TYPE_SHO, 0, 1.0, 128.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#endif + +/*******************/ +/* Lamp Datablocks */ + +DATABLOCK_GET(Lampmodule, lamp, getLampList()) + +// DATABLOCK_NEW(Lampmodule, Lamp, lamp_new()) + +static char Lampmodule_New_doc[] = +"() - returns new Lamp object"; + +PyObject *Lampmodule_New (PyObject *self, PyObject *args) +{ + Lamp *obj; + obj = lamp_new(); + return DataBlock_fromData(obj); +} + +#ifdef FUTURE_PYTHON_API + +DataBlockProperty Lamp_Properties[]= { + {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"energy", "energy", DBP_TYPE_FLO, 0, 0.0, 10.0}, + {"dist", "dist", DBP_TYPE_FLO, 0, 0.01, 5000.0}, + {"spotSize", "spotsize", DBP_TYPE_FLO, 0, 1.0, 180.0}, + {"spotBlend", "spotblend", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"haloInt", "haint", DBP_TYPE_FLO, 0, 0.0, 5.0}, + {"quad1", "att1", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"quad2", "att2", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"bufferSize", "bufsize", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"samples", "samp", DBP_TYPE_SHO, 0, 1.0, 16.0}, + {"haloStep", "shadhalostep", DBP_TYPE_SHO, 0, 0.0, 12.0}, + {"clipStart", "clipsta", DBP_TYPE_FLO, 0, 0.1, 5000.0}, + {"clipEnd", "clipend", DBP_TYPE_FLO, 0, 0.1, 5000.0}, + {"bias", "bias", DBP_TYPE_FLO, 0, 0.01, 5.0}, + {"softness", "soft", DBP_TYPE_FLO, 0, 1.00, 100.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; +#else + +DataBlockProperty Lamp_Properties[]= { + {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"type", "type", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"R", "r", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"G", "g", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"B", "b", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Energ", "energy", DBP_TYPE_FLO, 0, 0.0, 10.0}, + {"Dist", "dist", DBP_TYPE_FLO, 0, 0.01, 5000.0}, + {"SpotSi", "spotsize", DBP_TYPE_FLO, 0, 1.0, 180.0}, + {"SpotBl", "spotblend", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"HaloInt", "haint", DBP_TYPE_FLO, 0, 1.0, 5.0}, + {"Quad1", "att1", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Quad2", "att2", DBP_TYPE_FLO, 0, 0.0, 1.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#endif + + +static struct PyMethodDef Lampmodule_methods[] = { + {"New", Lampmodule_New, METH_VARARGS, Lampmodule_New_doc}, + {"get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc}, +#ifdef CURRENT_PYTHON_API + {"Get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc}, +#endif + {NULL, NULL} +}; + +DATABLOCK_ASSIGN_IPO(Lamp, lamp) // defines Lamp_assignIpo + +static struct PyMethodDef Lamp_methods[] = { + {"clrIpo", Lamp_clrIpo, METH_VARARGS, Lamp_clrIpo_doc}, + {"assignIpo", Lamp_assignIpo, METH_VARARGS, Lamp_assignIpo_doc}, + {NULL, NULL} +}; + +/********************/ +/* World Datablocks */ + +DATABLOCK_GET(Worldmodule, world, getWorldList() ) + +#ifdef FUTURE_PYTHON_API + +DataBlockProperty World_Properties[]= { + + {"mode", "mode", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"skyType", "skytype", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"mistType", "mistype", DBP_TYPE_SHO, 0, 0.0, 0.0}, + {"horR", "horr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"horG", "horg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"horB", "horb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ambR", "ambr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ambG", "ambg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ambB", "ambb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"zenR", "zenr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"zenG", "zeng", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"zenB", "zenb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"exposure", "exposure", DBP_TYPE_FLO, 0, 0.0, 5.0}, + {"mistStart", "miststa", DBP_TYPE_FLO, 0, 0.0, 1000.0}, + {"mistDepth", "mistdist", DBP_TYPE_FLO, 0, 0.0, 1000.0}, + {"mistHeight", "misthi", DBP_TYPE_FLO, 0, 0.0, 100.0}, + {"starDensity", "stardist", DBP_TYPE_FLO, 0, 2.0, 1000.0}, + {"starMinDist", "starmindist", DBP_TYPE_FLO, 0, 0.0, 1000.0}, + {"starSize", "starsize", DBP_TYPE_FLO, 0, 0.0, 10.0}, + {"starColNoise", "starcolsize", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"gravity", "gravity", DBP_TYPE_FLO, 0, 0.0, 25.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#else + +DataBlockProperty World_Properties[]= { + {"HorR", "horr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"HorG", "horg", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"HorB", "horb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ZenR", "zenr", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ZenG", "zeng", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"ZenB", "zenb", DBP_TYPE_FLO, 0, 0.0, 1.0}, + {"Expos", "exposure", DBP_TYPE_FLO, 0, 0.0, 5.0}, + {"MisSta", "miststa", DBP_TYPE_FLO, 0, 0.0, 1000.0}, + {"MisDi", "mistdist", DBP_TYPE_FLO, 0, 0.0, 1000.0}, + {"MisHi", "misthi", DBP_TYPE_FLO, 0, 0.0, 100.0}, + {"StarDi", "stardist", DBP_TYPE_FLO, 0, 2.0, 1000.0}, + {"StarSi", "starsize", DBP_TYPE_FLO, 0, 0.0, 10.0}, + + {"ipo", "*ipo", DBP_TYPE_FUN, 0, 0.0, 0.0, {0}, {0}, 0, 0, get_DataBlock_func}, + + {NULL} +}; + +#endif + +static char Worldmodule_getActive_doc[]="() - Returns the active world"; +static PyObject *Worldmodule_getActive (PyObject *self, PyObject *args) +{ + if (scene_getCurrent()->world) + return DataBlock_fromData(scene_getCurrent()->world); + else + return BPY_incr_ret(Py_None); +} + +static struct PyMethodDef Worldmodule_methods[] = { + // these for compatibility... + {"get", Worldmodule_get, METH_VARARGS, Worldmodule_get_doc}, +#ifdef CURRENT_PYTHON_API + {"Get", Worldmodule_get, METH_VARARGS, Worldmodule_get_doc}, +#endif + {"getCurrent", Worldmodule_getActive, METH_VARARGS, Worldmodule_getActive_doc}, + {NULL, NULL} +}; + + + +/* XXX these should go elsewhere */ + +PyObject *BPY_PyList_FromIDList(ListBase *list, DBConvertfunc convertfunc) +{ + PyObject *pylist= PyList_New(BLI_countlist(list)); + ID *id = list->first; + + int i=0; + + while (id) { + PyObject *ob= convertfunc(id); + + if (!ob) { + Py_DECREF(pylist); + return NULL; + } + PyList_SetItem(pylist, i, ob); + id = id->next; i++; + } + return pylist; +} + + +PyObject *py_find_from_list(ListBase *list, PyObject *args) { + char *name= NULL; + ID *id = list->first; + BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); + + if (name) { + while (id) { + if (strcmp(name, getIDName(id))==0) + return DataBlock_fromData(id); + + id= id->next; + } + return BPY_incr_ret(Py_None); + + } else + return BPY_PyList_FromIDList(list, DataBlock_fromData); +} + +PyObject *named_enum_get(int val, NamedEnum *enums) { + while (enums->name) { + if (enums->num == val) return PyString_FromString(enums->name); + enums++; + } + PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown enumerated type"); + return NULL; +} + +int named_enum_set(char *name, NamedEnum *enums) { + while (enums->name) { + if (STREQ(enums->name, name)) + return enums->num; + enums++; + } + + return -1; +} + +static int calc_offset_subsize(int *dlist, int *idx, int *subsize) { + int n= *dlist; + + if (n<=0) { + *subsize= -n; + return 0; + } else { + int ss; + int off= calc_offset_subsize(dlist+1, idx+1, &ss); + + *subsize= n*ss; + return off + (*idx)*ss; + } +} + +static int calc_offset(int *dlist, int *idx) { + int subsize; + return calc_offset_subsize(dlist, idx, &subsize); +} + +static void *get_db_ptr(DataBlockProperty *prop, char *structname, void *struct_ptr) { + int offset= BLO_findstruct_offset(structname, prop->struct_name); + void *ptr= struct_ptr; + + if (offset==-1) { + BPY_warn(("Internal error, Invalid prop entry\n")); + return NULL; + } + + ptr= (void *) (((char *)ptr) + offset); + + offset= calc_offset(prop->dlist, prop->idx); + ptr= (void *) (((char *)ptr) + offset); + + return ptr; +} + +PyObject *datablock_getattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr) { + if (STREQ(name, "properties") || STREQ(name, "__members__")) { + PyObject *l= PyList_New(0); + DataBlockProperty *p= props; + + while (p->public_name) { + PyList_Append(l, PyString_FromString(p->public_name)); + p++; + } + + return l; + } + + while (props->public_name) { + if (STREQ(name, props->public_name)) { + void *ptr = struct_ptr; + int val; + DBPtrToObFP conv_fp; + + if (props->handling==DBP_HANDLING_NONE || + props->handling==DBP_HANDLING_NENM) { + ptr= get_db_ptr(props, structname, struct_ptr); + if (!ptr) return NULL; + + } else if (props->handling==DBP_HANDLING_FUNC) { + DBGetPtrFP fp= (DBGetPtrFP) props->extra1; + ptr= fp(struct_ptr, props->struct_name, 0); + if (!ptr) return NULL; + } + + switch(props->type) { + case DBP_TYPE_CHA: + val= *((char *)ptr); + if (props->handling==DBP_HANDLING_NENM) + return named_enum_get(val, props->extra1); + else + return PyInt_FromLong(val); + case DBP_TYPE_SHO: + val= *((short *)ptr); + if (props->handling==DBP_HANDLING_NENM) + return named_enum_get(val, props->extra1); + else + return PyInt_FromLong(val); + case DBP_TYPE_INT: + val= *((int *)ptr); + if (props->handling==DBP_HANDLING_NENM) + return named_enum_get(val, props->extra1); + else + return PyInt_FromLong(val); + case DBP_TYPE_FLO: + return PyFloat_FromDouble ( *((float *)ptr) ); + case DBP_TYPE_VEC: + return newVectorObject ( ((float *)ptr), (int) props->min ); + case DBP_TYPE_FUN: + conv_fp= (DBPtrToObFP) props->extra2; + return conv_fp( ptr ); + default: + PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type"); + return NULL; + } + } + + props++; + } + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +int datablock_setattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr, PyObject *setto) { + + while (props->public_name) { + if (STREQ(props->public_name, name)) { + void *ptr = NULL; + int type; + DBSetPtrFP conv_fp; + int clamp= props->min!=props->max; + + int enum_val= -1; + char cha_data; + short sho_data; + int int_data; + float flo_data; + + type= props->stype; + if (type==DBP_TYPE_NON) type= props->type; + + if (props->handling==DBP_HANDLING_NONE) { + ptr= get_db_ptr(props, structname, struct_ptr); + if (!ptr) return 0; + + } else if (props->handling==DBP_HANDLING_FUNC) { + if (type!=DBP_TYPE_FUN) { + DBGetPtrFP fp= (DBGetPtrFP) props->extra1; + ptr= fp(struct_ptr, props->struct_name, 1); + if (!ptr) return 0; + } + } else if (props->handling==DBP_HANDLING_NENM) { + char *str; + if (!PyArg_Parse(setto, "s", &str)) return -1; + + ptr= get_db_ptr(props, structname, struct_ptr); + if (!ptr) return 0; + + enum_val= named_enum_set(str, props->extra1); + if (enum_val==-1) + return py_err_ret_int(PyExc_AttributeError, "invalid setting for field"); + } + + switch(type) { + case DBP_TYPE_CHA: + if (enum_val==-1) { + if (!PyArg_Parse(setto, "b", &cha_data)) return -1; + } else cha_data= (char) enum_val; + + if (clamp) { + CLAMP(cha_data, (char) props->min, (char) props->max); + } + *((char *)ptr)= cha_data; + return 0; + case DBP_TYPE_SHO: + if (enum_val==-1) { + if (!PyArg_Parse(setto, "h", &sho_data)) return -1; + } else sho_data= (short) enum_val; + + if (clamp) { + CLAMP(sho_data, (short) props->min, (short) props->max); + } + *((short *)ptr)= sho_data; + return 0; + case DBP_TYPE_INT: + if (enum_val==-1) { + if (!PyArg_Parse(setto, "i", &int_data)) return -1; + } else int_data= (int) enum_val; + + if (clamp) { + CLAMP(int_data, (int) props->min, (int) props->max); + } + *((int *)ptr)= int_data; + return 0; + case DBP_TYPE_FLO: + if (!PyArg_Parse(setto, "f", &flo_data)) return -1; + if (clamp) { + CLAMP(flo_data, (float) props->min, (float) props->max); + } + *((float *)ptr)= flo_data; + return 0; + case DBP_TYPE_VEC: + /* this is very dangerous!! TYPE_VEC also can contain non floats; see + * ipo curve attribute h1t, etc. */ + if (props->min == 3.0 ) { // vector triple + return BPY_parsefloatvector(setto, (float *) ptr, 3); + } else { + return py_err_ret_int(PyExc_AttributeError, "cannot directly assign, use slice assignment instead"); + } + return 0; + + case DBP_TYPE_FUN: + conv_fp= (DBSetPtrFP) props->extra3; + if (conv_fp) + return conv_fp( struct_ptr, props->struct_name, setto ); + else + return py_err_ret_int(PyExc_AttributeError, "cannot directly assign to item"); + default: + PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type"); + return -1; + } + } + + props++; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + +PyObject *datablock_assignIpo(DataBlock *block, DataBlock *ipoblock) +{ + Ipo **ipoptr; + Ipo *ipo; + + if (!DataBlock_isType(ipoblock, ID_IP)) { + PyErr_SetString(PyExc_TypeError, "expects Ipo object"); + return 0; + } + + ipo = PYBLOCK_AS_IPO(ipoblock); + + if (DataBlock_type(block) != ipo->blocktype) { + PyErr_SetString(PyExc_TypeError, "Ipo type does not match object type!"); + return 0; + } + + ipoptr = get_db_ptr(block->properties, "ipo", block->data); + if (!ipoptr) { + PyErr_SetString(PyExc_RuntimeError, "Object does not have an ipo!"); + return 0; + } + + *ipoptr = ipo; + Py_INCREF(Py_None); + return Py_None; +} + +/* deallocates a Python Datablock object */ +void DataBlock_dealloc(DataBlock *self) +{ +#ifdef REF_USERCOUNT + BOB_XDECUSER(DATABLOCK_ID(self)); // XXX abuse for ref count +#endif + PyMem_DEL(self); +} + +PyObject *DataBlock_repr(DataBlock *self) +{ + static char s[256]; + if (self->data) + sprintf (s, "[%.32s %.32s]", self->type, getIDName((ID*)self->data)); + else + sprintf (s, "[%.32s %.32s]", self->type, "<deleted>"); + return Py_BuildValue("s", s); +} + +/* ************************************************************************* */ +/* datablock linking */ + +/** Link data to Object */ + +static PyObject *link_Data_toObject(DataBlock *objectblk, DataBlock *datablk) +{ + Object *object = PYBLOCK_AS_OBJECT(objectblk); + + void *data = datablk->data; + if (!object_linkdata(object, data)) + { + PyErr_SetString(PyExc_TypeError, + "Object type different from Data type or linking for this type\ + not supported"); + return NULL; + } + Py_INCREF(Py_None); + return Py_None; +} + + +#ifdef USE_NMESH +/** Special function to link NMesh data to an Object */ +static PyObject *link_NMesh_toObject(DataBlock *objectblk, NMesh *nmesh) +{ + int retval; + Mesh *mesh = nmesh->mesh; + Object *obj = PYBLOCK_AS_OBJECT(objectblk); + + // if mesh was not created yet (mesh == 0), then do so: + if (!mesh) { + mesh = Mesh_fromNMesh(nmesh); // create and convert data + nmesh->mesh = mesh; + nmesh_updateMaterials(nmesh); + } + + retval = object_linkdata(obj, mesh); + if (!retval) { + PyErr_SetString(PyExc_RuntimeError, "failed to link NMesh data"); + if (!mesh) + printf("mesh data was null\n"); // XXX + return NULL; + } + synchronizeMaterialLists(obj, obj->data); + return Py_BuildValue("i", retval); +} + +#endif + +/** This is the generic function for linking objects with each other. + * It can be called on any DataBlock, as long as this makes sense. + * Example: + * + * from Blender import Object, Scene, NMesh + * ob = Object.get("Plane") + * scene = Scene.get("2") + * ob.link(scene) + * + * or + * + * nmesh = NMesh.GetRaw('Mesh') + * ob.link(nmesh) # instanciate mesh + * + */ + +static char DataBlock_link_doc[]= +"(object) - Links 'self' with the specified object.\n\ +Only the following object types can be linked to each other:\n\ + Scene -> Object\n\ + Object -> Data (Mesh, Curve, etc.)\n\ + Object -> Materials: [Material1, Material2, ...]\n\ +\n\ +The order of linking does not matter, i.e. the following both expressions\n\ +are valid:\n\ +\n\ + scene.link(object)\n\ +\n\ + object.link(scene)\n\ +"; + +PyObject *DataBlock_link(PyObject *self, PyObject *args) +{ + DataBlock *blockA= (DataBlock*) self; + PyObject *with; + DataBlock *blockB; + +#ifdef USE_NMESH + BPY_TRY(PyArg_ParseTuple(args, "O", &with)); + + blockB = (DataBlock *) with; +#else + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB)); +#endif + + switch (DataBlock_type(blockA)) { + case ID_OB: + // NMesh is no datablock object, so needs special treatment: +#ifdef USE_NMESH + if (NMesh_Check(with)) { + return link_NMesh_toObject(blockA, (NMesh *) with); + } +#endif + if (!DataBlock_Check(blockB)) { + PyErr_SetString(PyExc_TypeError, "Argument must be a DataBlock object!"); + return NULL; + } + return link_Data_toObject(blockA, blockB); + + default: + PyErr_SetString(PyExc_TypeError, "FATAL: implementation error, illegal link method"); + return NULL; + } +} + +/* unlinking currently disabled, but might me needed later + for other object types... + +static char DataBlock_unlink_doc[]= +"(object) - unlinks 'self' from the specified object.\n\ +See documentation for link() for valid object types."; + +static PyObject *DataBlock_unlink(PyObject *self, PyObject *args) +{ + DataBlock *blockA= (DataBlock*) self; + DataBlock *blockB; + + BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB)); + switch (DataBlock_type(blockA)) { + case ID_SCE: + switch(DataBlock_type(blockB)) { + case ID_OB: + return unlink_Object_fromScene(blockA, blockB); + default: + PyErr_SetString(PyExc_TypeError, "Scene unlink: invalid Object type"); + return NULL; + } + default: + PyErr_SetString(PyExc_TypeError, "cannot unlink: invalid object type"); + return NULL; + + } + +} +*/ + +/** These are the methods common to each datablock */ + +static struct PyMethodDef commonDataBlock_methods[] = { + {"link", DataBlock_link, METH_VARARGS, DataBlock_link_doc}, +// {"unlink", DataBlock_unlink, METH_VARARGS, DataBlock_unlink_doc}, + {NULL} +}; + +PyObject *DataBlock_getattr(PyObject *self, char *name) { + DataBlock *block= (DataBlock*) self; + PyObject *ret = NULL; + CHECK_VALIDDATA(block, "block was deleted!") + + // Check for common attributes: + if (STREQ(name, "name")) + return PyString_FromString((((ID*)block->data)->name)+2); + else if (STREQ(name, "block_type")) + return PyString_FromString(block->type); + else if (STREQ(name, "users")) + return PyInt_FromLong(((ID*)block->data)->us); + + // + // the following datablock types have methods: + switch (DataBlock_type(block)) { + case ID_OB: + ret = Py_FindMethod(Object_methods, self, name); + break; + case ID_IP: + ret = Py_FindMethod(Ipo_methods, self, name); + break; + case ID_CA: + ret = Py_FindMethod(Camera_methods, self, name); + break; + case ID_MA: + ret = Py_FindMethod(Material_methods, self, name); + break; + case ID_LA: + ret = Py_FindMethod(Lamp_methods, self, name); + break; + case ID_TXT: + ret = Py_FindMethod(Text_methods, self, name); + break; + } + if (ret) return ret; + PyErr_Clear(); // no method found, clear error + + // try common datablock methods + ret = Py_FindMethod(commonDataBlock_methods, (PyObject*)self, name); + if (ret) return ret; + + PyErr_Clear(); + + // try attributes from property list + ret = datablock_getattr(block->properties, block->type, name, block->data); + return ret; +} + +int DataBlock_setattr(PyObject *self, char *name, PyObject *ob) { + DataBlock *block= (DataBlock*) self; + + CHECK_VALIDDATA(block, "block was deleted!") + + if (STREQ(name, "name")) { + if (!PyArg_Parse(ob, "s", &name)) return -1; + + new_id(block->type_list, (ID*)block->data, name); + + return 0; + } + return datablock_setattr(block->properties, block->type, name, block->data, ob); +} + + +PyTypeObject DataBlock_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Block", /*tp_name*/ + sizeof(DataBlock), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor) DataBlock_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) DataBlock_getattr, /*tp_getattr*/ + (setattrfunc) DataBlock_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) DataBlock_repr, /*tp_repr*/ +}; + +/**************************************************************************/ + +/**********************/ +/* Texture Datablocks */ +/* +DATABLOCK_GET(Texturemodule, texture, getTextureList()) + +static struct PyMethodDef Texture_methods[] = { + {"Get", Texture_Get, 1, Texture_Get_doc}, + {NULL, NULL} +}; +*/ + + + +/* ---------------------------------------------------------------------- */ + +int DataBlock_type(DataBlock *block) +{ + return (GET_ID_TYPE((ID *) block->data)); +} + +int ObjectDataIDType(DataBlock *block) +{ + Object *ob; + if (!DataBlock_isType(block, ID_OB)) + return -1; + + ob = (Object *) block->data; + return GET_ID_TYPE((ID *) ob->data); +} + +int DataBlock_isType(DataBlock *block, int type) +{ + ID *id; + + if (!DataBlock_Check(block)) return 0; + id= (ID *) block->data; + return (GET_ID_TYPE(id))==type; +} + +/** This function creates a Python datablock descriptor object from + * the specified data pointer. This pointer must point to a structure + * with a valid ID header. + */ + +PyObject *DataBlock_fromData(void *data) { + DataBlock *newb; + ID *id= (ID *) data; + int idn; + + if (!data) return BPY_incr_ret(Py_None); + + idn = GET_ID_TYPE(id); + + if (idn==ID_OB) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Object"; + newb->type_list= getObjectList(); + newb->properties= Object_Properties; + + } else if (idn==ID_ME) { +#ifdef USE_NMESH + return newNMesh(data); +#else + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Mesh"; + newb->type_list= getMeshList(); + newb->properties= Mesh_Properties; +#endif + +// } else if (idn==ID_CU) { + /* Special case, should be fixed + * by proper high-level NURBS access. + * + * Later. + */ + +// return newNCurveObject(data); + + } else if (idn==ID_LA) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Lamp"; + newb->type_list= getLampList(); + newb->properties= Lamp_Properties; + + } else if (idn==ID_CA) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Camera"; + newb->type_list= getCameraList(); + newb->properties= Camera_Properties; + + } else if (idn==ID_MA) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Material"; + newb->type_list= getMaterialList(); + newb->properties= Material_Properties; + + } else if (idn==ID_WO) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "World"; + newb->type_list= getWorldList(); + newb->properties= World_Properties; + + } else if (idn==ID_IP) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Ipo"; + newb->type_list= getIpoList(); + newb->properties= Ipo_Properties; + +#ifdef EXPERIMENTAL + } else if (idn==ID_TE) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Tex"; + newb->type_list= getTextureList(); + newb->properties= Texture_Properties; +#endif + + } else if (idn==ID_IM) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Image"; + newb->type_list= getImageList(); + newb->properties= Image_Properties; + + } else if (idn==ID_TXT) { + newb= PyObject_NEW(DataBlock, &DataBlock_Type); + newb->type= "Text"; + newb->type_list= getTextList(); + newb->properties= Text_Properties; + } else return BPY_err_ret_ob(PyExc_SystemError, "unable to create Block for data"); + + newb->data= data; +#ifdef REF_USERCOUNT + BOB_INCUSER(id); // XXX abuse for refcount +#endif + + return (PyObject *) newb; +} + +PyObject *get_DataBlock_func(void **ptr) { + ID *id= (ID*) *ptr; + return DataBlock_fromData(id); +} + +/* ---------------------------------------------------------------------- */ +/* INIT ROUTINE */ + + +void init_types(PyObject *dict) +{ + PyObject *tmod, *tdict; + + tmod= Py_InitModule("Blender.Types", Null_methods); + PyDict_SetItemString(dict, "Types", tmod); + + tdict= PyModule_GetDict(tmod); + + PyDict_SetItemString(tdict, "IpoCurve", (PyObject *)&PyIpoCurve_Type); + PyDict_SetItemString(tdict, "BezTriple", (PyObject *)&PyBezTriple_Type); + + PyDict_SetItemString(tdict, "ButtonType", (PyObject *)&Button_Type); + PyDict_SetItemString(tdict, "BufferType", (PyObject *)&Buffer_Type); + PyDict_SetItemString(tdict, "NMeshType", (PyObject *)&NMesh_Type); + PyDict_SetItemString(tdict, "NMFaceType", (PyObject *)&NMFace_Type); + PyDict_SetItemString(tdict, "NMVertType", (PyObject *)&NMVert_Type); + PyDict_SetItemString(tdict, "NMColType", (PyObject *)&NMCol_Type); + + PyDict_SetItemString(tdict, "BlockType", (PyObject *)&DataBlock_Type); + + /* Setup external types */ + PyDict_SetItemString(tdict, "VectorType", (PyObject *)&Vector_Type); + PyDict_SetItemString(tdict, "MatrixType", (PyObject *)&Matrix_Type); +} + +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(LA_##name)) + +PyObject *initLamp(void) +{ + PyObject *mod, *dict, *d; + + mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Lamp", Lampmodule_methods); + dict= PyModule_GetDict(mod); + d = ConstObject_New(); + PyDict_SetItemString(dict, "Types", d); + + /* type */ + BPY_ADDCONST(d, LOCAL); + BPY_ADDCONST(d, SUN); + BPY_ADDCONST(d, SPOT); + BPY_ADDCONST(d, HEMI); + + d = ConstObject_New(); + PyDict_SetItemString(dict, "Modes", d); + + /* mode */ + BPY_ADDCONST(d, SHAD); + BPY_ADDCONST(d, HALO); + BPY_ADDCONST(d, LAYER); + BPY_ADDCONST(d, QUAD); + BPY_ADDCONST(d, NEG); + BPY_ADDCONST(d, ONLYSHADOW); + BPY_ADDCONST(d, SPHERE); + BPY_ADDCONST(d, SQUARE); + BPY_ADDCONST(d, TEXTURE); + BPY_ADDCONST(d, OSATEX); + BPY_ADDCONST(d, DEEP_SHADOW); + + return mod; +} + +PyObject *initMaterial(void) +{ + PyObject *mod, *dict, *d; + + mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Material", + Materialmodule_methods); + dict= PyModule_GetDict(mod); + d = ConstObject_New(); + PyDict_SetItemString(dict, "Modes", d); + + /* MATERIAL MODES + * ...some of these have really cryptic defines :-) + * We try to match them to the GUI descriptions... */ + +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) \ + insertConst(dict, #name, PyInt_FromLong(MA_##name)) + + insertConst(d, "TRACEABLE", PyInt_FromLong(MA_TRACEBLE)); + BPY_ADDCONST(d, SHADOW); + insertConst(d, "SHADELESS", PyInt_FromLong(MA_SHLESS)); + BPY_ADDCONST(d, WIRE); + insertConst(d, "VCOL_LIGHT", PyInt_FromLong(MA_VERTEXCOL)); + BPY_ADDCONST(d, HALO); + insertConst(d, "ZTRANSP", PyInt_FromLong(MA_ZTRA)); + insertConst(d, "VCOL_PAINT", PyInt_FromLong(MA_VERTEXCOLP)); + insertConst(d, "ZINVERT", PyInt_FromLong(MA_ZINV)); + BPY_ADDCONST(d, ONLYSHADOW); + BPY_ADDCONST(d, STAR); + insertConst(d, "TEXFACE", PyInt_FromLong(MA_FACETEXTURE)); + BPY_ADDCONST(d, NOMIST); + + /* HALO MODES */ + d = ConstObject_New(); + PyDict_SetItemString(dict, "HaloModes", d); + +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) \ + insertConst(dict, #name, PyInt_FromLong(MA_HALO_##name)) + + BPY_ADDCONST(d, RINGS); + BPY_ADDCONST(d, LINES); + insertConst(d, "TEX", PyInt_FromLong(MA_HALOTEX)); + insertConst(d, "PUNO", PyInt_FromLong(MA_HALOPUNO)); + BPY_ADDCONST(d, SHADE); + BPY_ADDCONST(d, FLARE); + + return mod; +} + +void init_Datablockmodules(PyObject *dict) { +#define MODLOAD(name) PyDict_SetItemString(dict, #name, Py_InitModule(MODNAME(BLENDERMODULE) "." #name, name##module_methods)) + + DataBlock_Type.ob_type = &PyType_Type; + PyIpoCurve_Type.ob_type= &PyType_Type; + PyBezTriple_Type.ob_type= &PyType_Type; + + PyDict_SetItemString(dict, "Object", initObject()); + PyDict_SetItemString(dict, "Lamp", initLamp()); + PyDict_SetItemString(dict, "Material", initMaterial()); + PyDict_SetItemString(dict, "Ipo", initIpo()); + PyDict_SetItemString(dict, "Scene", initScene()); + MODLOAD(Text); +// MODLOAD(Mesh); + MODLOAD(Camera); + MODLOAD(World); + MODLOAD(Image); +/* MODLOAD(Texture); */ +} diff --git a/source/blender/bpython/intern/opy_datablock.h b/source/blender/bpython/intern/opy_datablock.h new file mode 100644 index 00000000000..437b551a754 --- /dev/null +++ b/source/blender/bpython/intern/opy_datablock.h @@ -0,0 +1,193 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include "BSE_edit.h" // for getname_< >_ei() +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +/* for a few protos: only*/ +#include "BKE_library.h" +#include "BKE_object.h" +#include "BKE_ika.h" +#include "BKE_ipo.h" +#include "BKE_key.h" + +#include "BLI_blenlib.h" +#include "BLO_genfile.h" // BLO_findstruct_offset() +#include "DNA_ID.h" +#include "DNA_curve_types.h" +#include "DNA_scene_types.h" +#include "DNA_key_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_ipo_types.h" +#include "DNA_lamp_types.h" +#include "DNA_ika_types.h" + +#include "BPY_constobject.h" + +typedef struct _NamedEnum { + char *name; + int num; +} NamedEnum; + +extern PyTypeObject DataBlock_Type; + +#define DataBlock_Check(v) ((v)->ob_type == &DataBlock_Type) + +typedef struct _DataBlockProperty { + char *public_name; + char *struct_name; + + int type; +#define DBP_TYPE_CHA 1 /* Char item */ +#define DBP_TYPE_SHO 2 /* Short item */ +#define DBP_TYPE_INT 3 /* Int item */ +#define DBP_TYPE_FLO 4 /* Float item */ +#define DBP_TYPE_VEC 5 /* Float vector object */ +#define DBP_TYPE_FUN 6 /* Extra2 hold function to convert ptr->ob + extra3 holds function to convert ob->ptr */ + + int stype; +#define DBP_TYPE_NON 0 + + float min; /* Minimum allowed value */ + float max; /* Maximum allowed value */ + + int idx[4]; + int dlist[4]; + + int handling; +#define DBP_HANDLING_NONE 0 /* No special handling required */ +#define DBP_HANDLING_FUNC 1 /* Extra1 is used to retrieve ptr */ +#define DBP_HANDLING_NENM 2 /* Extra1 holds named enum to resolve + values from/to. */ + + void *extra1; + void *extra2; + void *extra3; +} DataBlockProperty; + + +/* function pointers needed for callbacks */ + +typedef void *(*DBGetPtrFP) (void *struct_ptr, char *name, int forsetting); +typedef PyObject * (*DBPtrToObFP) (void **ptr); +typedef int (*DBSetPtrFP) (void *struct_ptr, char *name, PyObject *ob); +typedef PyObject *(*DBConvertfunc) (void *data); + + +typedef struct { + PyObject_HEAD + void *data; + char *type; + ListBase *type_list; + DataBlockProperty *properties; +} DataBlock; + +/* PROTOS */ + +/* opy_datablock.c */ +PyObject *BPY_PyList_FromIDList(ListBase *list, DBConvertfunc convertfunc); +PyObject *get_DataBlock_func(void **p); + +PyObject *py_find_from_list (ListBase *list, PyObject *args); +PyObject *named_enum_get (int val, NamedEnum *enums); +int named_enum_set (char *name, NamedEnum *enums); +PyObject *datablock_getattr (DataBlockProperty *props, char *structname, + char *name, void *struct_ptr); +int datablock_setattr (DataBlockProperty *props, char *structname, + char *name, void *struct_ptr, PyObject *setto); +PyObject *datablock_assignIpo(DataBlock *block, DataBlock *ipoblock); + + +/* DataBlock Methods */ + +void DataBlock_dealloc (DataBlock *self); +int DataBlock_print (PyObject *self, FILE *fp, int flags); +PyObject *DataBlock_getattr (PyObject *self, char *name); +int DataBlock_setattr (PyObject *self, char *name, PyObject *ob); +int DataBlock_type(DataBlock *block); +int DataBlock_isType (DataBlock *block, int type); +PyObject *DataBlock_fromData (void *data); +PyObject *DataBlock_link(PyObject *self, PyObject *args); + +PyObject *make_icu_list (ListBase *curves); +void pybzt_dealloc (PyObject *self); +int pybzt_print (PyObject *self, FILE *fp, int flags); +PyObject *pybzt_getattr (PyObject *self, char *name); +int pybzt_setattr (PyObject *self, char *name, PyObject *ob); +PyObject *pybzt_create (PyObject *self, PyObject *args); +PyObject *pybzt_from_bzt (BezTriple *bzt); +void pyicu_dealloc (PyObject *self); +int pyicu_print (PyObject *self, FILE *fp, int flags); +PyObject *pyicu_getattr (PyObject *self, char *name); +int pyicu_setattr (PyObject *self, char *name, PyObject *ob); +PyObject *pyicu_from_icu (IpoCurve *icu); +PyObject *Ipo_Recalc (PyObject *self, PyObject *args); +PyObject *Ipo_Eval (PyObject *self, PyObject *args); +void init_types (PyObject *dict); +void init_Datablockmodules (PyObject *dict); +PyObject *getInverseMatrix(void *vdata); + + +/* Object module */ +void *Object_special_getattr(void *vdata, char *name); +int Object_special_setattr(void *vdata, char *name, PyObject *py_ob); + +extern PyObject *initObject(void); +extern struct PyMethodDef Objectmodule_methods[]; +extern struct PyMethodDef Object_methods[]; +extern DataBlockProperty Object_Properties[]; + +extern struct PyMethodDef Imagemodule_methods[]; +extern DataBlockProperty Image_Properties[]; +extern PyObject *initScene(void); +extern struct PyMethodDef Scenemodule_methods[]; + +extern PyObject *initIpo(void); +extern struct PyMethodDef Ipo_methods[]; +extern struct PyMethodDef Ipomodule_methods[]; +extern DataBlockProperty Ipo_Properties[]; + + +extern struct PyMethodDef Textmodule_methods[]; +extern struct PyMethodDef Text_methods[]; +extern DataBlockProperty Text_Properties[]; + + + +struct Material; + +struct +Material **newMaterialList_fromPyList(PyObject *list); +PyObject *PyList_fromMaterialList(struct Material **matlist, int len); diff --git a/source/blender/bpython/intern/opy_draw.c b/source/blender/bpython/intern/opy_draw.c new file mode 100644 index 00000000000..23929b1392f --- /dev/null +++ b/source/blender/bpython/intern/opy_draw.c @@ -0,0 +1,2679 @@ +/* python.c MIXED MODEL + * + * june 99 + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +#include "BMF_Api.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_text_types.h" + +#include "BKE_global.h" + +#include "BIF_gl.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_interface.h" +#include "BIF_mywindow.h" + +#include "interface.h" +#include "mydevice.h" /* for all the event constants */ + +#include "Python.h" +#include "BPY_macros.h" +#include "BPY_main.h" +#include "BPY_tools.h" + +int disable_force_draw= 0; + +/* hack to flag that window redraw has happened inside slider callback: */ + +static void exit_pydraw (SpaceText *st); +static uiBlock *Get_uiBlock (void); +void initDraw (void); + +/* Button Object */ + +typedef struct _Button { + PyObject_VAR_HEAD + + int type; /* 1 == int, 2 == float, 3 == string */ + int slen; /* length of string (if type == 3) */ + union { + int asint; + float asfloat; + char *asstr; + } val; +} Button; + + +static void Button_dealloc(PyObject *self) { + Button *but= (Button*) self; + + if(but->type==3) MEM_freeN(but->val.asstr); + + PyMem_DEL(self); +} + +static PyObject *Button_getattr(PyObject *self, char *name) { + Button *but= (Button*) self; + + if(STREQ(name, "val")) { + if (but->type==1) + return Py_BuildValue("i", but->val.asint); + else if (but->type==2) + return Py_BuildValue("f", but->val.asfloat); + else if (but->type==3) + return Py_BuildValue("s", but->val.asstr); + } + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static int Button_setattr(PyObject *self, char *name, PyObject *v) { + Button *but= (Button*) self; + + if(STREQ(name, "val")) { + if (but->type==1) + PyArg_Parse(v, "i", &but->val.asint); + else if (but->type==2) + PyArg_Parse(v, "f", &but->val.asfloat); + else if (but->type==3) { + char *newstr; + + PyArg_Parse(v, "s", &newstr); + strncpy(but->val.asstr, newstr, but->slen); + } + } else { + PyErr_SetString(PyExc_AttributeError, name); + return -1; + } + + return 0; +} + +static PyObject *Button_repr(PyObject *self) { + return PyObject_Repr(Button_getattr(self, "val")); +} + +PyTypeObject Button_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Button", /*tp_name*/ + sizeof(Button), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor) Button_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) Button_getattr, /*tp_getattr*/ + (setattrfunc) Button_setattr, /*tp_setattr*/ + (cmpfunc) 0, /*tp_cmp*/ + (reprfunc) Button_repr, /*tp_repr*/ +}; + + +static Button *newbutton (void) { + Button *but= (Button *) PyObject_NEW(Button, &Button_Type); + + return but; +} + + +/* GUI interface routines */ + +static void exit_pydraw(SpaceText *st) +{ + scrarea_queue_redraw(st->area); + + if (st) { + Py_XDECREF((PyObject *) st->py_draw); + Py_XDECREF((PyObject *) st->py_event); + Py_XDECREF((PyObject *) st->py_button); + + st->py_draw= st->py_event= st->py_button= NULL; + } +} + +static void exec_callback(SpaceText *st, PyObject *callback, PyObject *args) +{ + PyObject *result= PyEval_CallObject(callback, args); + + if (result==NULL) { + st->text->compiled= NULL; + PyErr_Print(); + exit_pydraw(st); + } + Py_XDECREF(result); + Py_DECREF(args); +} + +/* the handler for drawing routines (see Register method) */ + +void BPY_spacetext_do_pywin_draw(SpaceText *st) +{ + uiBlock *block; + char butblock[20]; + + sprintf(butblock, "win %d", curarea->win); + block= uiNewBlock(&curarea->uiblocks, butblock, UI_EMBOSSX, UI_HELV, curarea->win); + + if (st->py_draw) { + glPushAttrib(GL_ALL_ATTRIB_BITS); + exec_callback(st, st->py_draw, Py_BuildValue("()")); + glPopAttrib(); + } else { + glClearColor(0.4375, 0.4375, 0.4375, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } + + uiDrawBlock(block); + + curarea->win_swap= WIN_BACK_OK; +} + +/* the handler for button event routines (see Register method) */ + +static void spacetext_do_pywin_buttons(SpaceText *st, unsigned short event) { + if (st->py_button) { + exec_callback(st, st->py_button, Py_BuildValue("(i)", event)); + } +} + +/* calls the generic event handling methods registered with Register */ + +void BPY_spacetext_do_pywin_event(SpaceText *st, unsigned short event, short val) { + if (event==QKEY && G.qual & (LR_ALTKEY|LR_CTRLKEY|LR_SHIFTKEY)) { + exit_pydraw(st); + return; + } + + if (val) { + if (uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + + if (event==UI_BUT_EVENT) { + spacetext_do_pywin_buttons(st, val); + } + } + + if (st->py_event) { + exec_callback(st, st->py_event, Py_BuildValue("(ii)", event, val)); + } +} + +int BPY_spacetext_is_pywin(SpaceText *st) { + return (st->py_draw || st->py_event || st->py_button); +} + +static char Method_Exit_doc[]= +"() - Exit the windowing interface"; +static PyObject *Method_Exit (PyObject *self, PyObject *args) +{ + SpaceText *st= curarea->spacedata.first; +#ifdef CLEAR_NAMESPACE + PyObject *d; +#endif + BPY_TRY(PyArg_ParseTuple(args, "")); + + exit_pydraw(st); +#ifdef CLEAR_NAMESPACE + d = st->py_globaldict; // The current window's global namespace dictionary + if (d) { + PyDict_Clear(d); + Py_DECREF(d); // release dictionary + } +#endif + + return BPY_incr_ret(Py_None); +} + +static char Method_Register_doc[]= +"(draw, event, button) - Register callbacks for windowing\n\ +\n\ +(draw) A function to draw the screen, taking no arguments\n\ +(event) A function to handle events, taking 2 arguments (evt, val)\n\ + (evt) The event number\n\ + (val) The value modifier (for key and mouse press/release)\n\ +(button) A function to handle button events, taking 1 argument (evt)\n\ + (evt) The button number\n\ +\n\ +A None object can be passed if a callback is unused."; + +static PyObject *Method_Register (PyObject *self, PyObject *args) +{ + PyObject *newdrawc= NULL, *neweventc= NULL, *newbuttonc= NULL; + SpaceText *st= curarea->spacedata.first; + + BPY_TRY(PyArg_ParseTuple(args, "O|OO", &newdrawc, &neweventc, &newbuttonc)); + + /* This is a hack again: + * Every python script should actually do a global variable cleanup at + * the end of execution. + * For scripts registering GUI callbacks, this does not work, because + * the global namespace of the interpreter still needs to be accessed + * from the callback. + * Workaround: a text object has a flag which allows the global name + * space to be cleared at the end of the script. This flag should be + * normally set when executed with Alt-P. For a script registering with + * the GUI though, clear the flag and set it when the GUI mode is left + * (Method_Exit). + */ + + BPY_debug(("--- disable clear namespace")); + + st->flags &= ~ST_CLEAR_NAMESPACE; + + + if (!PyCallable_Check(newdrawc)) newdrawc= NULL; + if (!PyCallable_Check(neweventc)) neweventc= NULL; + if (!PyCallable_Check(newbuttonc)) newbuttonc= NULL; + + if (!(newdrawc || neweventc || newbuttonc)) + return BPY_incr_ret(Py_None); + + exit_pydraw(st); + + Py_XINCREF(newdrawc); + Py_XINCREF(neweventc); + Py_XINCREF(newbuttonc); + + st->py_draw= newdrawc; + st->py_event= neweventc; + st->py_button= newbuttonc; + + scrarea_queue_redraw(st->area); + + return BPY_incr_ret(Py_None); +} + + +static char Method_Redraw_doc[]= +"([after]) - Queue a redraw event\n\ +\n\ +[after=0] Determines whether the redraw is processed before or after other input events.\n\ +\n\ +Redraw events are buffered so that regardless of how many events are queued\n\ +the window only receives one redraw event."; + +static PyObject *Method_Redraw (PyObject *self, PyObject *args) +{ + int after= 0; + + BPY_TRY(PyArg_ParseTuple(args, "|i", &after)); + + if (after) addafterqueue(curarea->win, REDRAW, 1); + else scrarea_queue_winredraw(curarea); + + return BPY_incr_ret(Py_None); +} + + +static char Method_Draw_doc[]= +"() - Force an immediate redraw\n\ +\n\ +Forced redraws are not buffered, in other words the window is redrawn\n\ +exactly once for everytime this function is called."; +static PyObject *Method_Draw (PyObject *self, PyObject *args) +{ + /* If forced drawing is disable queue a redraw event instead */ + if (disable_force_draw) { + scrarea_queue_winredraw(curarea); + return BPY_incr_ret(Py_None); + } + + BPY_TRY(PyArg_ParseTuple(args, "")); + + scrarea_do_windraw(curarea); + + screen_swapbuffers(); + + return BPY_incr_ret(Py_None); +} + + + +static char Method_Create_doc[]= +"(value) - Create a default Button object\n\ +\n\ +(value) - The value to store in the button\n\ +\n\ +Valid values are ints, floats, and strings"; + +static PyObject *Method_Create (PyObject *self, PyObject *args) +{ + Button *but; + PyObject *in; + + BPY_TRY(PyArg_ParseTuple(args, "O", &in)); + + but= newbutton(); + if(PyFloat_Check(in)) { + but->type= 2; + but->val.asfloat= PyFloat_AsDouble(in); + } else if (PyInt_Check(in)) { + but->type= 1; + but->val.asint= PyInt_AsLong(in); + } else if (PyString_Check(in)) { + char *newstr= PyString_AsString(in); + + but->type= 3; + but->slen= strlen(newstr); + but->val.asstr= MEM_mallocN(but->slen+1, "button string"); + + strcpy(but->val.asstr, newstr); + } + + return (PyObject *) but; +} + +static uiBlock *Get_uiBlock(void) +{ + char butblock[32]; + + sprintf(butblock, "win %d", curarea->win); + + return uiGetBlock(butblock, curarea); +} + +static char Method_Button_doc[]= +"(name, event, x, y, width, height, [tooltip]) - Create a new Button (push) button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_Button (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL; + int event; + int x, y, w, h; + + BPY_TRY(PyArg_ParseTuple(args, "siiiii|s", &name, &event, &x, &y, &w, &h, &tip)); + + block= Get_uiBlock(); + + if(block) uiDefBut(block, BUT, event, name, x, y, w, h, 0, 0, 0, 0, 0, tip); + + return BPY_incr_ret(Py_None); +} + +static char Method_Menu_doc[]= +"(name, event, x, y, width, height, default, [tooltip]) - Create a new Menu button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(default) The number of the option to be selected by default\n\ +[tooltip=""] The button's tooltip\n\ +\n\ +The menu options are specified through the name of the\n\ +button. Options are followed by a format code and seperated\n\ +by the '|' (pipe) character.\n\ +Valid format codes are\n\ + %t - The option should be used as the title\n\ + %xN - The option should set the integer N in the button value."; + +static PyObject *Method_Menu (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL; + int event, def; + int x, y, w, h; + Button *but; + + BPY_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event, &x, &y, &w, &h, &def, &tip)); + + but= newbutton(); + but->type= 1; + but->val.asint= def; + + block= Get_uiBlock(); + if(block) uiDefButI(block, MENU, event, name, x, y, w, h, &but->val.asint, 0, 0, 0, 0, tip); + + return (PyObject *) but; +} + +static char Method_Toggle_doc[]= +"(name, event, x, y, width, height, default, [tooltip]) - Create a new Toggle button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(default) An integer (0 or 1) specifying the default state\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_Toggle (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL; + int event; + int x, y, w, h, def; + Button *but; + + BPY_TRY(PyArg_ParseTuple(args, "siiiiii|s", &name, &event, &x, &y, &w, &h, &def, &tip)); + + but= newbutton(); + but->type= 1; + but->val.asint= def; + + block= Get_uiBlock(); + if(block) uiDefButI(block, TOG, event, name, x, y, w, h, &but->val.asint, 0, 0, 0, 0, tip); + + return (PyObject *) but; +} + + +/* DO NOT TOUCH THIS FUNCTION ! + Redrawing a slider inside its own callback routine is actually forbidden + with the current toolkit architecture (button routines are not reentrant). + But it works anyway. + XXX This is condemned to be dinosource in future - it's a hack. + */ + +static void py_slider_update(void *butv, void *data2_unused) +{ + uiBut *but= butv; + + disable_force_draw= 1; + /* + Disable forced drawing, otherwise the button object which + is still being used might be deleted + */ + +// UIfrontbuf = 0; +// spacetext_do_pywin_buttons(curarea->spacedata.first, but->retval); + + g_window_redrawn = 0; + curarea->win_swap= WIN_BACK_OK; + UIfrontbuf = 1; + spacetext_do_pywin_buttons(curarea->spacedata.first, uiButGetRetVal(but)); + UIfrontbuf = 0; + + if (!g_window_redrawn) /* if Redraw already called */ + Windowmodule_Redraw(0, Py_BuildValue("(i)", SPACE_VIEW3D)); + + disable_force_draw= 0; +} + +static char Method_Slider_doc[]= +"(name, event, x, y, width, height, initial, min, max, [update, tooltip]) - Create a new Slider button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\ +[update=1] A value controlling whether the slider will emit events as it is edited.\n\ + A non-zero value (default) enables the events. A zero value supresses them.\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_Slider (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL; + int event; + int x, y, w, h, realtime=1; + Button *but; + PyObject *mino, *maxo, *inio; + + BPY_TRY(PyArg_ParseTuple(args, "siiiiiOOO|is", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip)); + + + but= newbutton(); + if (PyFloat_Check(inio)) { + float ini, min, max; + + ini= PyFloat_AsDouble(inio); + min= PyFloat_AsDouble(mino); + max= PyFloat_AsDouble(maxo); + + but->type= 2; + but->val.asfloat= ini; + + block= Get_uiBlock(); + if(block) { + uiBut *ubut; + ubut= uiDefButF(block, NUMSLI, event, name, x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip); + if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL); + } + } + else { + int ini, min, max; + + ini= PyInt_AsLong(inio); + min= PyInt_AsLong(mino); + max= PyInt_AsLong(maxo); + + but->type= 1; + but->val.asint= ini; + + block= Get_uiBlock(); + if(block) { + uiBut *ubut; + ubut= uiDefButI(block, NUMSLI, event, name, x, y, w, h, &but->val.asint, min, max, 0, 0, tip); + if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL); + } + } + return (PyObject *) but; +} + +static char Method_Scrollbar_doc[]= +"(event, x, y, width, height, initial, min, max, [update, tooltip]) - Create a new Scrollbar\n\ +\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\ +[update=1] A value controlling whether the slider will emit events as it is edited.\n\ + A non-zero value (default) enables the events. A zero value supresses them.\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_Scrollbar (PyObject *self, PyObject *args) +{ + char *tip= NULL; + uiBlock *block; + int event; + int x, y, w, h, realtime=1; + Button *but; + PyObject *mino, *maxo, *inio; + float ini, min, max; + + BPY_TRY(PyArg_ParseTuple(args, "iiiiiOOO|is", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip)); + + if (!PyNumber_Check(inio) || !PyNumber_Check(inio) || !PyNumber_Check(inio)) + return BPY_err_ret_ob(PyExc_AttributeError, "expected numbers for initial, min, and max"); + + but= newbutton(); + + if (PyFloat_Check(inio)) but->type= 2; + else but->type= 1; + + ini= PyFloat_AsDouble(inio); + min= PyFloat_AsDouble(mino); + max= PyFloat_AsDouble(maxo); + + if (but->type==2) { + but->val.asfloat= ini; + block= Get_uiBlock(); + if(block) { + uiBut *ubut; + ubut= uiDefButF(block, SCROLL, event, "", x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip); + if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL); + } + } else { + but->val.asint= ini; + block= Get_uiBlock(); + if(block) { + uiBut *ubut; + ubut= uiDefButI(block, SCROLL, event, "", x, y, w, h, &but->val.asint, min, max, 0, 0, tip); + if (realtime) uiButSetFunc(ubut, py_slider_update, ubut, NULL); + } + } + + return (PyObject *) but; +} + +static char Method_Number_doc[]= +"(name, event, x, y, width, height, initial, min, max, [tooltip]) - Create a new Number button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(initial, min, max) Three values (int or float) specifying the initial and limit values.\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_Number (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL; + int event; + int x, y, w, h; + Button *but; + PyObject *mino, *maxo, *inio; + + BPY_TRY(PyArg_ParseTuple(args, "siiiiiOOO|s", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip)); + + but= newbutton(); + + if (PyFloat_Check(inio)) { + float ini, min, max; + + ini= PyFloat_AsDouble(inio); + min= PyFloat_AsDouble(mino); + max= PyFloat_AsDouble(maxo); + + but->type= 2; + but->val.asfloat= ini; + + block= Get_uiBlock(); + if(block) uiDefButF(block, NUM, event, name, x, y, w, h, &but->val.asfloat, min, max, 0, 0, tip); + } else { + int ini, min, max; + + ini= PyInt_AsLong(inio); + min= PyInt_AsLong(mino); + max= PyInt_AsLong(maxo); + + but->type= 1; + but->val.asint= ini; + + block= Get_uiBlock(); + if(block) uiDefButI(block, NUM, event, name, x, y, w, h, &but->val.asint, min, max, 0, 0, tip); + } + + return (PyObject *) but; +} + +static char Method_String_doc[]= +"(name, event, x, y, width, height, initial, length, [tooltip]) - Create a new String button\n\ +\n\ +(name) A string to display on the button\n\ +(event) The event number to pass to the button event function when activated\n\ +(x, y) The lower left coordinate of the button\n\ +(width, height) The button width and height\n\ +(initial) The string to display initially\n\ +(length) The maximum input length\n\ +[tooltip=""] The button's tooltip"; + +static PyObject *Method_String (PyObject *self, PyObject *args) +{ + uiBlock *block; + char *name, *tip= NULL, *newstr; + int event; + int x, y, w, h, len; + Button *but; + + BPY_TRY(PyArg_ParseTuple(args, "siiiiisi|s", &name, &event, &x, &y, &w, &h, &newstr, &len, &tip)); + + but= newbutton(); + but->type= 3; + but->slen= len; + but->val.asstr= MEM_mallocN(len+1, "button string"); + + strncpy(but->val.asstr, newstr, len); + but->val.asstr[len]= 0; + + block= Get_uiBlock(); + if(block) uiDefBut(block, TEX, event, name, x, y, w, h, but->val.asstr, 0, len, 0, 0, tip); + + return (PyObject *) but; +} + +static char Method_Text_doc[]= +"(text) - Draw text onscreen\n\ +\n\ +(text) The text to draw\n"; +static PyObject *Method_Text (PyObject *self, PyObject *args) +{ + char *text; + + BPY_TRY(PyArg_ParseTuple(args, "s", &text)); + + BMF_DrawString(G.font, text); + + return BPY_incr_ret(Py_None); +} + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Method) + +static struct PyMethodDef Draw_methods[] = { + MethodDef(Create), + MethodDef(Button), + MethodDef(Toggle), + MethodDef(Menu), + MethodDef(Slider), + MethodDef(Scrollbar), + MethodDef(Number), + MethodDef(String), + + MethodDef(Text), + + MethodDef(Exit), + MethodDef(Redraw), + MethodDef(Draw), + MethodDef(Register), + + {NULL, NULL} +}; + +PyObject *init_py_draw(void) +{ + PyObject *mod= Py_InitModule(SUBMODULE(Draw), Draw_methods); + PyObject *dict= PyModule_GetDict(mod); + + Button_Type.ob_type= &PyType_Type; + + BPY_ADDCONST(dict, LEFTMOUSE); + BPY_ADDCONST(dict, MIDDLEMOUSE); + BPY_ADDCONST(dict, RIGHTMOUSE); + BPY_ADDCONST(dict, MOUSEX); + BPY_ADDCONST(dict, MOUSEY); + BPY_ADDCONST(dict, TIMER0); + BPY_ADDCONST(dict, TIMER1); + BPY_ADDCONST(dict, TIMER2); + BPY_ADDCONST(dict, TIMER3); + BPY_ADDCONST(dict, KEYBD); + BPY_ADDCONST(dict, RAWKEYBD); + BPY_ADDCONST(dict, REDRAW); + BPY_ADDCONST(dict, INPUTCHANGE); + BPY_ADDCONST(dict, QFULL); + BPY_ADDCONST(dict, WINFREEZE); + BPY_ADDCONST(dict, WINTHAW); + BPY_ADDCONST(dict, WINCLOSE); + BPY_ADDCONST(dict, WINQUIT); +#ifndef IRISGL + BPY_ADDCONST(dict, Q_FIRSTTIME); +#endif + BPY_ADDCONST(dict, AKEY); + BPY_ADDCONST(dict, BKEY); + BPY_ADDCONST(dict, CKEY); + BPY_ADDCONST(dict, DKEY); + BPY_ADDCONST(dict, EKEY); + BPY_ADDCONST(dict, FKEY); + BPY_ADDCONST(dict, GKEY); + BPY_ADDCONST(dict, HKEY); + BPY_ADDCONST(dict, IKEY); + BPY_ADDCONST(dict, JKEY); + BPY_ADDCONST(dict, KKEY); + BPY_ADDCONST(dict, LKEY); + BPY_ADDCONST(dict, MKEY); + BPY_ADDCONST(dict, NKEY); + BPY_ADDCONST(dict, OKEY); + BPY_ADDCONST(dict, PKEY); + BPY_ADDCONST(dict, QKEY); + BPY_ADDCONST(dict, RKEY); + BPY_ADDCONST(dict, SKEY); + BPY_ADDCONST(dict, TKEY); + BPY_ADDCONST(dict, UKEY); + BPY_ADDCONST(dict, VKEY); + BPY_ADDCONST(dict, WKEY); + BPY_ADDCONST(dict, XKEY); + BPY_ADDCONST(dict, YKEY); + BPY_ADDCONST(dict, ZKEY); + BPY_ADDCONST(dict, ZEROKEY); + BPY_ADDCONST(dict, ONEKEY); + BPY_ADDCONST(dict, TWOKEY); + BPY_ADDCONST(dict, THREEKEY); + BPY_ADDCONST(dict, FOURKEY); + BPY_ADDCONST(dict, FIVEKEY); + BPY_ADDCONST(dict, SIXKEY); + BPY_ADDCONST(dict, SEVENKEY); + BPY_ADDCONST(dict, EIGHTKEY); + BPY_ADDCONST(dict, NINEKEY); + BPY_ADDCONST(dict, CAPSLOCKKEY); + BPY_ADDCONST(dict, LEFTCTRLKEY); + BPY_ADDCONST(dict, LEFTALTKEY); + BPY_ADDCONST(dict, RIGHTALTKEY); + BPY_ADDCONST(dict, RIGHTCTRLKEY); + BPY_ADDCONST(dict, RIGHTSHIFTKEY); + BPY_ADDCONST(dict, LEFTSHIFTKEY); + BPY_ADDCONST(dict, ESCKEY); + BPY_ADDCONST(dict, TABKEY); + BPY_ADDCONST(dict, RETKEY); + BPY_ADDCONST(dict, SPACEKEY); + BPY_ADDCONST(dict, LINEFEEDKEY); + BPY_ADDCONST(dict, BACKSPACEKEY); + BPY_ADDCONST(dict, DELKEY); + BPY_ADDCONST(dict, SEMICOLONKEY); + BPY_ADDCONST(dict, PERIODKEY); + BPY_ADDCONST(dict, COMMAKEY); + BPY_ADDCONST(dict, QUOTEKEY); + BPY_ADDCONST(dict, ACCENTGRAVEKEY); + BPY_ADDCONST(dict, MINUSKEY); + BPY_ADDCONST(dict, SLASHKEY); + BPY_ADDCONST(dict, BACKSLASHKEY); + BPY_ADDCONST(dict, EQUALKEY); + BPY_ADDCONST(dict, LEFTBRACKETKEY); + BPY_ADDCONST(dict, RIGHTBRACKETKEY); + BPY_ADDCONST(dict, LEFTARROWKEY); + BPY_ADDCONST(dict, DOWNARROWKEY); + BPY_ADDCONST(dict, RIGHTARROWKEY); + BPY_ADDCONST(dict, UPARROWKEY); + BPY_ADDCONST(dict, PAD2); + BPY_ADDCONST(dict, PAD4); + BPY_ADDCONST(dict, PAD6); + BPY_ADDCONST(dict, PAD8); + BPY_ADDCONST(dict, PAD1); + BPY_ADDCONST(dict, PAD3); + BPY_ADDCONST(dict, PAD5); + BPY_ADDCONST(dict, PAD7); + BPY_ADDCONST(dict, PAD9); + BPY_ADDCONST(dict, PADPERIOD); + BPY_ADDCONST(dict, PADSLASHKEY); + BPY_ADDCONST(dict, PADASTERKEY); + BPY_ADDCONST(dict, PAD0); + BPY_ADDCONST(dict, PADMINUS); + BPY_ADDCONST(dict, PADENTER); + BPY_ADDCONST(dict, PADPLUSKEY); + BPY_ADDCONST(dict, F1KEY); + BPY_ADDCONST(dict, F2KEY); + BPY_ADDCONST(dict, F3KEY); + BPY_ADDCONST(dict, F4KEY); + BPY_ADDCONST(dict, F5KEY); + BPY_ADDCONST(dict, F6KEY); + BPY_ADDCONST(dict, F7KEY); + BPY_ADDCONST(dict, F8KEY); + BPY_ADDCONST(dict, F9KEY); + BPY_ADDCONST(dict, F10KEY); + BPY_ADDCONST(dict, F11KEY); + BPY_ADDCONST(dict, F12KEY); + BPY_ADDCONST(dict, PAUSEKEY); + BPY_ADDCONST(dict, INSERTKEY); + BPY_ADDCONST(dict, HOMEKEY); + BPY_ADDCONST(dict, PAGEUPKEY); + BPY_ADDCONST(dict, PAGEDOWNKEY); + BPY_ADDCONST(dict, ENDKEY); + + return mod; +} + + +/* Buffer Object */ + +/* For Python access to OpenGL functions requiring + * a pointer. + */ + +PyTypeObject Buffer_Type; + +typedef struct _Buffer { + PyObject_VAR_HEAD + + PyObject *parent; + + int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */ + int ndimensions; + int *dimensions; + + union { + char *asbyte; + short *asshort; + int *asint; + float *asfloat; + + void *asvoid; + } buf; +} Buffer; + +static int type_size(int type) { + switch (type) { + case GL_BYTE: + return sizeof(char); + case GL_SHORT: + return sizeof(short); + case GL_INT: + return sizeof(int); + case GL_FLOAT: + return sizeof(float); + } + return -1; +} + +static Buffer *make_buffer(int type, int ndimensions, int *dimensions) { + Buffer *buffer; + void *buf= NULL; + int i, size, length; + + length= 1; + for (i=0; i<ndimensions; i++) length*= dimensions[i]; + + size= type_size(type); + + buf= MEM_mallocN(length*size, "Buffer buffer"); + + buffer= (Buffer *) PyObject_NEW(Buffer, &Buffer_Type); + buffer->parent= NULL; + buffer->ndimensions= ndimensions; + buffer->dimensions= dimensions; + buffer->type= type; + buffer->buf.asvoid= buf; + + for (i= 0; i<length; i++) { + if (type==GL_BYTE) + buffer->buf.asbyte[i]= 0; + + else if (type==GL_SHORT) + buffer->buf.asshort[i]= 0; + + else if (type==GL_INT) + buffer->buf.asint[i]= 0; + + else if (type==GL_FLOAT) + buffer->buf.asfloat[i]= 0.0; + } + + return buffer; +} + +static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq); + +static char Method_Buffer_doc[]= +"(type, dimensions, [template]) - Create a new Buffer object\n\ +\n\ +(type) - The format to store data in\n\ +(dimensions) - An int or sequence specifying the dimensions of the buffer\n\ +[template] - A sequence of matching dimensions to the buffer to be created\n\ + which will be used to initialize the Buffer.\n\ +\n\ +If a template is not passed in all fields will be initialized to 0.\n\ +\n\ +The type should be one of GL_BYTE, GL_SHORT, GL_INT, or GL_FLOAT.\n\ +If the dimensions are specified as an int a linear buffer will be\n\ +created. If a sequence is passed for the dimensions the buffer\n\ +will have len(sequence) dimensions, where the size for each dimension\n\ +is determined by the value in the sequence at that index.\n\ +\n\ +For example, passing [100, 100] will create a 2 dimensional\n\ +square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\ +buffer which is twice as deep as it is wide or high."; + +static PyObject *Method_Buffer (PyObject *self, PyObject *args) +{ + PyObject *length_ob= NULL, *template= NULL; + Buffer *buffer; + + int i, type; + int *dimensions = 0, ndimensions = 0; + + BPY_TRY(PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template)); + + if (type!=GL_BYTE && type!=GL_SHORT && type!=GL_INT && type!=GL_FLOAT) { + PyErr_SetString(PyExc_AttributeError, "type"); + return NULL; + } + + if (PyNumber_Check(length_ob)) { + ndimensions= 1; + dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions"); + dimensions[0]= PyInt_AsLong(length_ob); + + } else if (PySequence_Check(length_ob)) { + ndimensions= PySequence_Length(length_ob); + dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions"); + + for (i=0; i<ndimensions; i++) { + PyObject *ob= PySequence_GetItem(length_ob, i); + + if (!PyNumber_Check(ob)) dimensions[i]= 1; + else dimensions[i]= PyInt_AsLong(ob); + + Py_DECREF(ob); + } + } + + buffer= make_buffer(type, ndimensions, dimensions); + if (template && ndimensions) { + if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], template)) { + Py_DECREF(buffer); + return NULL; + } + } + + return (PyObject *) buffer; +} + +/**********/ + + +/* Buffer sequence methods */ + +static int Buffer_len(PyObject *self) { + Buffer *buf= (Buffer *) self; + + return buf->dimensions[0]; +} + +static PyObject *Buffer_item(PyObject *self, int i) { + Buffer *buf= (Buffer *) self; + + if (i >= buf->dimensions[0]) { + PyErr_SetString(PyExc_IndexError, "array index out of range"); + return NULL; + } + + if (buf->ndimensions==1) { + switch (buf->type) { + case GL_BYTE: return Py_BuildValue("b", buf->buf.asbyte[i]); + case GL_SHORT: return Py_BuildValue("h", buf->buf.asshort[i]); + case GL_INT: return Py_BuildValue("i", buf->buf.asint[i]); + case GL_FLOAT: return Py_BuildValue("f", buf->buf.asfloat[i]); + } + } else { + Buffer *newbuf; + int j, length, size; + + length= 1; + for (j=1; j<buf->ndimensions; j++) { + length*= buf->dimensions[j]; + } + size= type_size(buf->type); + + newbuf= (Buffer *) PyObject_NEW(Buffer, &Buffer_Type); + + Py_INCREF(self); + newbuf->parent= self; + + newbuf->ndimensions= buf->ndimensions-1; + newbuf->type= buf->type; + newbuf->buf.asvoid= buf->buf.asbyte + i*length*size; + + newbuf->dimensions= MEM_mallocN(newbuf->ndimensions*sizeof(int), "Buffer dimensions"); + memcpy(newbuf->dimensions, buf->dimensions+1, newbuf->ndimensions*sizeof(int)); + + return (PyObject *) newbuf; + } + + return NULL; +} + +static PyObject *Buffer_slice(PyObject *self, int begin, int end) +{ + Buffer *buf= (Buffer *) self; + PyObject *list; + int count; + + if (begin<0) begin= 0; + if (end>buf->dimensions[0]) end= buf->dimensions[0]; + if (begin>end) begin= end; + + list= PyList_New(end-begin); + + for (count= begin; count<end; count++) + PyList_SetItem(list, count-begin, Buffer_item(self, count)); + + return list; +} + +static int Buffer_ass_item(PyObject *self, int i, PyObject *v) { + Buffer *buf= (Buffer *) self; + + if (i >= buf->dimensions[0]) { + PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); + return -1; + } + + if (buf->ndimensions!=1) { + PyObject *row= Buffer_item(self, i); + int ret; + + if (!row) return -1; + + ret= Buffer_ass_slice(row, 0, buf->dimensions[1], v); + Py_DECREF(row); + + return ret; + } + + if (buf->type==GL_BYTE) { + if (!PyArg_Parse(v, "b;Coordinates must be ints", &buf->buf.asbyte[i])) + return -1; + + } else if (buf->type==GL_SHORT) { + if (!PyArg_Parse(v, "h;Coordinates must be ints", &buf->buf.asshort[i])) + return -1; + + } else if (buf->type==GL_INT) { + if (!PyArg_Parse(v, "i;Coordinates must be ints", &buf->buf.asint[i])) + return -1; + + } else if (buf->type==GL_FLOAT) { + if (!PyArg_Parse(v, "f;Coordinates must be floats", &buf->buf.asfloat[i])) + return -1; + } + + return 0; +} + +static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq) +{ + Buffer *buf= (Buffer *) self; + PyObject *item; + int count, err=0; + + if (begin<0) begin= 0; + if (end>buf->dimensions[0]) end= buf->dimensions[0]; + if (begin>end) begin= end; + + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation"); + return -1; + } + + if (PySequence_Length(seq)!=(end-begin)) { + PyErr_SetString(PyExc_TypeError, "size mismatch in assignment"); + return -1; + } + + for (count= begin; count<end; count++) { + item= PySequence_GetItem(seq, count-begin); + err= Buffer_ass_item(self, count, item); + Py_DECREF(item); + + if (err) break; + } + + return err; +} +static PySequenceMethods Buffer_SeqMethods = { + (inquiry) Buffer_len, /*sq_length*/ + (binaryfunc) 0, /*sq_concat*/ + (intargfunc) 0, /*sq_repeat*/ + (intargfunc) Buffer_item, /*sq_item*/ + (intintargfunc) Buffer_slice, /*sq_slice*/ + (intobjargproc) Buffer_ass_item, /*sq_ass_item*/ + (intintobjargproc) Buffer_ass_slice, /*sq_ass_slice*/ +}; + + + +/**********/ + +static void Buffer_dealloc(PyObject *self) { + Buffer *buf= (Buffer *) self; + + if (buf->parent) Py_DECREF(buf->parent); + else MEM_freeN(buf->buf.asvoid); + + MEM_freeN(buf->dimensions); + + PyMem_DEL(self); +} + +static PyObject *Buffer_tolist(PyObject *self) { + int i, len= ((Buffer *)self)->dimensions[0]; + PyObject *list= PyList_New(len); + + for (i=0; i<len; i++) { + PyList_SetItem(list, i, Buffer_item(self, i)); + } + + return list; +} + +static PyObject *Buffer_dimensions(PyObject *self) { + Buffer *buffer= (Buffer *) self; + PyObject *list= PyList_New(buffer->ndimensions); + int i; + + for (i= 0; i<buffer->ndimensions; i++) { + PyList_SetItem(list, i, PyInt_FromLong(buffer->dimensions[i])); + } + + return list; +} + +static PyObject *Buffer_getattr(PyObject *self, char *name) { + if (strcmp(name, "list")==0) return Buffer_tolist(self); + else if (strcmp(name, "dimensions")==0) return Buffer_dimensions(self); + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static PyObject *Buffer_repr(PyObject *self) { + PyObject *list= Buffer_tolist(self); + PyObject *repr= PyObject_Repr(list); + Py_DECREF(list); + + return repr; +} + +PyTypeObject Buffer_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Buffer", /*tp_name*/ + sizeof(Buffer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor) Buffer_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) Buffer_getattr, /*tp_getattr*/ + (setattrfunc) 0, /*tp_setattr*/ + (cmpfunc) 0, /*tp_compare*/ + (reprfunc) Buffer_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &Buffer_SeqMethods, /*tp_as_sequence*/ +}; + +#ifndef __APPLE__ +/* By golly George! It looks like fancy pants macro time!!! */ + +/* +#define int_str "i" +#define int_var(number) bgl_int##number +#define int_ref(number) &bgl_int##number +#define int_def(number) int int_var(number) + +#define float_str "f" +#define float_var(number) bgl_float##number +#define float_ref(number) &bgl_float##number +#define float_def(number) float float_var(number) +*/ + +/* TYPE_str is the string to pass to Py_ArgParse (for the format) */ +/* TYPE_var is the name to pass to the GL function */ +/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */ +/* TYPE_def is the C initialization of the variable */ + +#define void_str "" +#define void_var(num) +#define void_ref(num) &bgl_var##num +#define void_def(num) char bgl_var##num + +#define buffer_str "O!" +#define buffer_var(number) (bgl_buffer##number)->buf.asvoid +#define buffer_ref(number) &Buffer_Type, &bgl_buffer##number +#define buffer_def(number) Buffer *bgl_buffer##number + +/* GL Pointer fields, handled by buffer type */ +/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP */ + +#define GLbooleanP_str "O!" +#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLbooleanP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLbooleanP_def(number) Buffer *bgl_buffer##number + +#define GLbyteP_str "O!" +#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLbyteP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLbyteP_def(number) Buffer *bgl_buffer##number + +#define GLubyteP_str "O!" +#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLubyteP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLubyteP_def(number) Buffer *bgl_buffer##number + +#define GLintP_str "O!" +#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLintP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLintP_def(number) Buffer *bgl_buffer##number + +#define GLuintP_str "O!" +#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLuintP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLuintP_def(number) Buffer *bgl_buffer##number + +#define GLshortP_str "O!" +#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLshortP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLshortP_def(number) Buffer *bgl_buffer##number + +#define GLushortP_str "O!" +#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLushortP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLushortP_def(number) Buffer *bgl_buffer##number + +#define GLfloatP_str "O!" +#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLfloatP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLfloatP_def(number) Buffer *bgl_buffer##number + +#define GLdoubleP_str "O!" +#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLdoubleP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLdoubleP_def(number) Buffer *bgl_buffer##number + +#define GLclampfP_str "O!" +#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLclampfP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLclampfP_def(number) Buffer *bgl_buffer##number + +#define GLvoidP_str "O!" +#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid +#define GLvoidP_ref(number) &Buffer_Type, &bgl_buffer##number +#define GLvoidP_def(number) Buffer *bgl_buffer##number + +#define buffer_str "O!" +#define buffer_var(number) (bgl_buffer##number)->buf.asvoid +#define buffer_ref(number) &Buffer_Type, &bgl_buffer##number +#define buffer_def(number) Buffer *bgl_buffer##number + +/* The standard GL typedefs are used as prototypes, we can't + * use the GL type directly because Py_ArgParse expects normal + * C types. + * + * Py_ArgParse doesn't grok writing into unsigned variables, + * so we use signed everything (even stuff that should be unsigned. + */ + +/* typedef unsigned int GLenum; */ +#define GLenum_str "i" +#define GLenum_var(num) bgl_var##num +#define GLenum_ref(num) &bgl_var##num +#define GLenum_def(num) /* unsigned */ int GLenum_var(num) + +/* typedef unsigned int GLboolean; */ +#define GLboolean_str "b" +#define GLboolean_var(num) bgl_var##num +#define GLboolean_ref(num) &bgl_var##num +#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num) + +/* typedef unsigned int GLbitfield; */ +#define GLbitfield_str "i" +#define GLbitfield_var(num) bgl_var##num +#define GLbitfield_ref(num) &bgl_var##num +#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num) + +/* typedef signed char GLbyte; */ +#define GLbyte_str "b" +#define GLbyte_var(num) bgl_var##num +#define GLbyte_ref(num) &bgl_var##num +#define GLbyte_def(num) signed char GLbyte_var(num) + +/* typedef short GLshort; */ +#define GLshort_str "h" +#define GLshort_var(num) bgl_var##num +#define GLshort_ref(num) &bgl_var##num +#define GLshort_def(num) short GLshort_var(num) + +/* typedef int GLint; */ +#define GLint_str "i" +#define GLint_var(num) bgl_var##num +#define GLint_ref(num) &bgl_var##num +#define GLint_def(num) int GLint_var(num) + +/* typedef int GLsizei; */ +#define GLsizei_str "i" +#define GLsizei_var(num) bgl_var##num +#define GLsizei_ref(num) &bgl_var##num +#define GLsizei_def(num) int GLsizei_var(num) + +/* typedef unsigned char GLubyte; */ +#define GLubyte_str "b" +#define GLubyte_var(num) bgl_var##num +#define GLubyte_ref(num) &bgl_var##num +#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num) + +/* typedef unsigned short GLushort; */ +#define GLushort_str "h" +#define GLushort_var(num) bgl_var##num +#define GLushort_ref(num) &bgl_var##num +#define GLushort_def(num) /* unsigned */ short GLushort_var(num) + +/* typedef unsigned int GLuint; */ +#define GLuint_str "i" +#define GLuint_var(num) bgl_var##num +#define GLuint_ref(num) &bgl_var##num +#define GLuint_def(num) /* unsigned */ int GLuint_var(num) + +/* typedef float GLfloat; */ +#define GLfloat_str "f" +#define GLfloat_var(num) bgl_var##num +#define GLfloat_ref(num) &bgl_var##num +#define GLfloat_def(num) float GLfloat_var(num) + +/* typedef float GLclampf; */ +#define GLclampf_str "f" +#define GLclampf_var(num) bgl_var##num +#define GLclampf_ref(num) &bgl_var##num +#define GLclampf_def(num) float GLclampf_var(num) + +/* typedef double GLdouble; */ +#define GLdouble_str "d" +#define GLdouble_var(num) bgl_var##num +#define GLdouble_ref(num) &bgl_var##num +#define GLdouble_def(num) double GLdouble_var(num) + +/* typedef double GLclampd; */ +#define GLclampd_str "d" +#define GLclampd_var(num) bgl_var##num +#define GLclampd_ref(num) &bgl_var##num +#define GLclampd_def(num) double GLclampd_var(num) + +/* typedef void GLvoid; */ +/* #define GLvoid_str "" */ +/* #define GLvoid_var(num) bgl_var##num */ +/* #define GLvoid_ref(num) &bgl_var##num */ +/* #define GLvoid_def(num) char bgl_var##num */ + +#define arg_def1(a1) a1##_def(1) +#define arg_def2(a1, a2) arg_def1(a1); a2##_def(2) +#define arg_def3(a1, a2, a3) arg_def2(a1, a2); a3##_def(3) +#define arg_def4(a1, a2, a3, a4) arg_def3(a1, a2, a3); a4##_def(4) +#define arg_def5(a1, a2, a3, a4, a5) arg_def4(a1, a2, a3, a4); a5##_def(5) +#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6) +#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7) +#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8) +#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9) +#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10) + +#define arg_var1(a1) a1##_var(1) +#define arg_var2(a1, a2) arg_var1(a1), a2##_var(2) +#define arg_var3(a1, a2, a3) arg_var2(a1, a2), a3##_var(3) +#define arg_var4(a1, a2, a3, a4) arg_var3(a1, a2, a3), a4##_var(4) +#define arg_var5(a1, a2, a3, a4, a5) arg_var4(a1, a2, a3, a4), a5##_var(5) +#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6) +#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7) +#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8) +#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9) +#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10) + +#define arg_ref1(a1) a1##_ref(1) +#define arg_ref2(a1, a2) arg_ref1(a1), a2##_ref(2) +#define arg_ref3(a1, a2, a3) arg_ref2(a1, a2), a3##_ref(3) +#define arg_ref4(a1, a2, a3, a4) arg_ref3(a1, a2, a3), a4##_ref(4) +#define arg_ref5(a1, a2, a3, a4, a5) arg_ref4(a1, a2, a3, a4), a5##_ref(5) +#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6) +#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7) +#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8) +#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9) +#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10) + +#define arg_str1(a1) a1##_str +#define arg_str2(a1, a2) arg_str1(a1) a2##_str +#define arg_str3(a1, a2, a3) arg_str2(a1, a2) a3##_str +#define arg_str4(a1, a2, a3, a4) arg_str3(a1, a2, a3) a4##_str +#define arg_str5(a1, a2, a3, a4, a5) arg_str4(a1, a2, a3, a4) a5##_str +#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str +#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str +#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str +#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str +#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str + +#define ret_def_void +#define ret_set_void +#define ret_ret_void return BPY_incr_ret(Py_None) + +#define ret_def_GLint int ret_int +#define ret_set_GLint ret_int= +#define ret_ret_GLint return PyInt_FromLong(ret_int); + +#define ret_def_GLuint unsigned int ret_uint +#define ret_set_GLuint ret_uint= +#define ret_ret_GLuint return PyInt_FromLong((long) ret_uint); + +#define ret_def_GLenum unsigned int ret_uint +#define ret_set_GLenum ret_uint= +#define ret_ret_GLenum return PyInt_FromLong((long) ret_uint); + +#define ret_def_GLboolean unsigned char ret_bool +#define ret_set_GLboolean ret_bool= +#define ret_ret_GLboolean return PyInt_FromLong((long) ret_bool); + +#define ret_def_GLstring const unsigned char *ret_str; +#define ret_set_GLstring ret_str= +#define ret_ret_GLstring return PyString_FromString(ret_str); + +#define BGL_Wrap(nargs, funcname, ret, arg_list) \ +static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\ + arg_def##nargs arg_list; \ + ret_def_##ret; \ + if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\ + ret_set_##ret gl##funcname (arg_var##nargs arg_list);\ + ret_ret_##ret; \ +} + +BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) +BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) +BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP)) +BGL_Wrap(1, Begin, void, (GLenum)) +BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) +BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP)) +BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum)) +BGL_Wrap(1, CallList, void, (GLuint)) +BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP)) +BGL_Wrap(1, Clear, void, (GLbitfield)) +BGL_Wrap(4, ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(4, ClearColor, void, (GLclampf, GLclampf, GLclampf, GLclampf)) +BGL_Wrap(1, ClearDepth, void, (GLclampd)) +BGL_Wrap(1, ClearIndex, void, (GLfloat)) +BGL_Wrap(1, ClearStencil, void, (GLint)) +BGL_Wrap(2, ClipPlane, void, (GLenum, GLdoubleP)) +BGL_Wrap(3, Color3b, void, (GLbyte, GLbyte, GLbyte)) +BGL_Wrap(1, Color3bv, void, (GLbyteP)) +BGL_Wrap(3, Color3d, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, Color3dv, void, (GLdoubleP)) +BGL_Wrap(3, Color3f, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, Color3fv, void, (GLfloatP)) +BGL_Wrap(3, Color3i, void, (GLint, GLint, GLint)) +BGL_Wrap(1, Color3iv, void, (GLintP)) +BGL_Wrap(3, Color3s, void, (GLshort, GLshort, GLshort)) +BGL_Wrap(1, Color3sv, void, (GLshortP)) +BGL_Wrap(3, Color3ub, void, (GLubyte, GLubyte, GLubyte)) +BGL_Wrap(1, Color3ubv, void, (GLubyteP)) +BGL_Wrap(3, Color3ui, void, (GLuint, GLuint, GLuint)) +BGL_Wrap(1, Color3uiv, void, (GLuintP)) +BGL_Wrap(3, Color3us, void, (GLushort, GLushort, GLushort)) +BGL_Wrap(1, Color3usv, void, (GLushortP)) +BGL_Wrap(4, Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte)) +BGL_Wrap(1, Color4bv, void, (GLbyteP)) +BGL_Wrap(4, Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, Color4dv, void, (GLdoubleP)) +BGL_Wrap(4, Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, Color4fv, void, (GLfloatP)) +BGL_Wrap(4, Color4i, void, (GLint, GLint, GLint, GLint)) +BGL_Wrap(1, Color4iv, void, (GLintP)) +BGL_Wrap(4, Color4s, void, (GLshort, GLshort, GLshort, GLshort)) +BGL_Wrap(1, Color4sv, void, (GLshortP)) +BGL_Wrap(4, Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte)) +BGL_Wrap(1, Color4ubv, void, (GLubyteP)) +BGL_Wrap(4, Color4ui, void, (GLuint, GLuint, GLuint, GLuint)) +BGL_Wrap(1, Color4uiv, void, (GLuintP)) +BGL_Wrap(4, Color4us, void, (GLushort, GLushort, GLushort, GLushort)) +BGL_Wrap(1, Color4usv, void, (GLushortP)) +BGL_Wrap(4, ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean)) +BGL_Wrap(2, ColorMaterial, void, (GLenum, GLenum)) +BGL_Wrap(5, CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum)) +BGL_Wrap(1, CullFace, void, (GLenum)) +BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei)) +BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) +BGL_Wrap(1, DepthFunc, void, (GLenum)) +BGL_Wrap(1, DepthMask, void, (GLboolean)) +BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd)) +BGL_Wrap(1, Disable, void, (GLenum)) +BGL_Wrap(1, DrawBuffer, void, (GLenum)) +BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP)) +BGL_Wrap(1, EdgeFlag, void, (GLboolean)) +BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP)) +BGL_Wrap(1, Enable, void, (GLenum)) +BGL_Wrap(1, End, void, (void)) +BGL_Wrap(1, EndList, void, (void)) +BGL_Wrap(1, EvalCoord1d, void, (GLdouble)) +BGL_Wrap(1, EvalCoord1dv, void, (GLdoubleP)) +BGL_Wrap(1, EvalCoord1f, void, (GLfloat)) +BGL_Wrap(1, EvalCoord1fv, void, (GLfloatP)) +BGL_Wrap(2, EvalCoord2d, void, (GLdouble, GLdouble)) +BGL_Wrap(1, EvalCoord2dv, void, (GLdoubleP)) +BGL_Wrap(2, EvalCoord2f, void, (GLfloat, GLfloat)) +BGL_Wrap(1, EvalCoord2fv, void, (GLfloatP)) +BGL_Wrap(3, EvalMesh1, void, (GLenum, GLint, GLint)) +BGL_Wrap(5, EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint)) +BGL_Wrap(1, EvalPoint1, void, (GLint)) +BGL_Wrap(2, EvalPoint2, void, (GLint, GLint)) +BGL_Wrap(3, FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP)) +BGL_Wrap(1, Finish, void, (void)) +BGL_Wrap(1, Flush, void, (void)) +BGL_Wrap(2, Fogf, void, (GLenum, GLfloat)) +BGL_Wrap(2, Fogfv, void, (GLenum, GLfloatP)) +BGL_Wrap(2, Fogi, void, (GLenum, GLint)) +BGL_Wrap(2, Fogiv, void, (GLenum, GLintP)) +BGL_Wrap(1, FrontFace, void, (GLenum)) +BGL_Wrap(6, Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, GenLists, GLuint, (GLsizei)) +BGL_Wrap(2, GenTextures, void, (GLsizei, GLuintP)) +BGL_Wrap(2, GetBooleanv, void, (GLenum, GLbooleanP)) +BGL_Wrap(2, GetClipPlane, void, (GLenum, GLdoubleP)) +BGL_Wrap(2, GetDoublev, void, (GLenum, GLdoubleP)) +BGL_Wrap(1, GetError, GLenum, (void)) +BGL_Wrap(2, GetFloatv, void, (GLenum, GLfloatP)) +BGL_Wrap(2, GetIntegerv, void, (GLenum, GLintP)) +BGL_Wrap(3, GetLightfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetLightiv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(3, GetMapdv, void, (GLenum, GLenum, GLdoubleP)) +BGL_Wrap(3, GetMapfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetMapiv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(3, GetMaterialfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetMaterialiv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(2, GetPixelMapfv, void, (GLenum, GLfloatP)) +BGL_Wrap(2, GetPixelMapuiv, void, (GLenum, GLuintP)) +BGL_Wrap(2, GetPixelMapusv, void, (GLenum, GLushortP)) +BGL_Wrap(1, GetPolygonStipple, void, (GLubyteP)) +BGL_Wrap(1, GetString, GLstring, (GLenum)) +BGL_Wrap(3, GetTexEnvfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetTexEnviv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(3, GetTexGendv, void, (GLenum, GLenum, GLdoubleP)) +BGL_Wrap(3, GetTexGenfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetTexGeniv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(5, GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP)) +BGL_Wrap(4, GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP)) +BGL_Wrap(4, GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP)) +BGL_Wrap(3, GetTexParameterfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, GetTexParameteriv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(2, Hint, void, (GLenum, GLenum)) +BGL_Wrap(1, IndexMask, void, (GLuint)) +BGL_Wrap(1, Indexd, void, (GLdouble)) +BGL_Wrap(1, Indexdv, void, (GLdoubleP)) +BGL_Wrap(1, Indexf, void, (GLfloat)) +BGL_Wrap(1, Indexfv, void, (GLfloatP)) +BGL_Wrap(1, Indexi, void, (GLint)) +BGL_Wrap(1, Indexiv, void, (GLintP)) +BGL_Wrap(1, Indexs, void, (GLshort)) +BGL_Wrap(1, Indexsv, void, (GLshortP)) +BGL_Wrap(1, InitNames, void, (void)) +BGL_Wrap(1, IsEnabled, GLboolean, (GLenum)) +BGL_Wrap(1, IsList, GLboolean, (GLuint)) +BGL_Wrap(1, IsTexture, GLboolean, (GLuint)) +BGL_Wrap(2, LightModelf, void, (GLenum, GLfloat)) +BGL_Wrap(2, LightModelfv, void, (GLenum, GLfloatP)) +BGL_Wrap(2, LightModeli, void, (GLenum, GLint)) +BGL_Wrap(2, LightModeliv, void, (GLenum, GLintP)) +BGL_Wrap(3, Lightf, void, (GLenum, GLenum, GLfloat)) +BGL_Wrap(3, Lightfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint)) +BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(2, LineStipple, void, (GLint, GLushort)) +BGL_Wrap(1, LineWidth, void, (GLfloat)) +BGL_Wrap(1, ListBase, void, (GLuint)) +BGL_Wrap(1, LoadIdentity, void, (void)) +BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP)) +BGL_Wrap(1, LoadMatrixf, void, (GLfloatP)) +BGL_Wrap(1, LoadName, void, (GLuint)) +BGL_Wrap(1, LogicOp, void, (GLenum)) +BGL_Wrap(6, Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP)) +BGL_Wrap(6, Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP)) +BGL_Wrap(10, Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP)) +BGL_Wrap(10, Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP)) +BGL_Wrap(3, MapGrid1d, void, (GLint, GLdouble, GLdouble)) +BGL_Wrap(3, MapGrid1f, void, (GLint, GLfloat, GLfloat)) +BGL_Wrap(6, MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble)) +BGL_Wrap(6, MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat)) +BGL_Wrap(3, Materialf, void, (GLenum, GLenum, GLfloat)) +BGL_Wrap(3, Materialfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, Materiali, void, (GLenum, GLenum, GLint)) +BGL_Wrap(3, Materialiv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(1, MatrixMode, void, (GLenum)) +BGL_Wrap(1, MultMatrixd, void, (GLdoubleP)) +BGL_Wrap(1, MultMatrixf, void, (GLfloatP)) +BGL_Wrap(2, NewList, void, (GLuint, GLenum)) +BGL_Wrap(3, Normal3b, void, (GLbyte, GLbyte, GLbyte)) +BGL_Wrap(1, Normal3bv, void, (GLbyteP)) +BGL_Wrap(3, Normal3d, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, Normal3dv, void, (GLdoubleP)) +BGL_Wrap(3, Normal3f, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, Normal3fv, void, (GLfloatP)) +BGL_Wrap(3, Normal3i, void, (GLint, GLint, GLint)) +BGL_Wrap(1, Normal3iv, void, (GLintP)) +BGL_Wrap(3, Normal3s, void, (GLshort, GLshort, GLshort)) +BGL_Wrap(1, Normal3sv, void, (GLshortP)) +BGL_Wrap(6, Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, PassThrough, void, (GLfloat)) +BGL_Wrap(3, PixelMapfv, void, (GLenum, GLint, GLfloatP)) +BGL_Wrap(3, PixelMapuiv, void, (GLenum, GLint, GLuintP)) +BGL_Wrap(3, PixelMapusv, void, (GLenum, GLint, GLushortP)) +BGL_Wrap(2, PixelStoref, void, (GLenum, GLfloat)) +BGL_Wrap(2, PixelStorei, void, (GLenum, GLint)) +BGL_Wrap(2, PixelTransferf, void, (GLenum, GLfloat)) +BGL_Wrap(2, PixelTransferi, void, (GLenum, GLint)) +BGL_Wrap(2, PixelZoom, void, (GLfloat, GLfloat)) +BGL_Wrap(1, PointSize, void, (GLfloat)) +BGL_Wrap(2, PolygonMode, void, (GLenum, GLenum)) +BGL_Wrap(2, PolygonOffset, void, (GLfloat, GLfloat)) +BGL_Wrap(1, PolygonStipple, void, (GLubyteP)) +BGL_Wrap(1, PopAttrib, void, (void)) +BGL_Wrap(1, PopMatrix, void, (void)) +BGL_Wrap(1, PopName, void, (void)) +BGL_Wrap(3, PrioritizeTextures, void, (GLsizei, GLuintP, GLclampfP)) +BGL_Wrap(1, PushAttrib, void, (GLbitfield)) +BGL_Wrap(1, PushMatrix, void, (void)) +BGL_Wrap(1, PushName, void, (GLuint)) +BGL_Wrap(2, RasterPos2d, void, (GLdouble, GLdouble)) +BGL_Wrap(1, RasterPos2dv, void, (GLdoubleP)) +BGL_Wrap(2, RasterPos2f, void, (GLfloat, GLfloat)) +BGL_Wrap(1, RasterPos2fv, void, (GLfloatP)) +BGL_Wrap(2, RasterPos2i, void, (GLint, GLint)) +BGL_Wrap(1, RasterPos2iv, void, (GLintP)) +BGL_Wrap(2, RasterPos2s, void, (GLshort, GLshort)) +BGL_Wrap(1, RasterPos2sv, void, (GLshortP)) +BGL_Wrap(3, RasterPos3d, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, RasterPos3dv, void, (GLdoubleP)) +BGL_Wrap(3, RasterPos3f, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, RasterPos3fv, void, (GLfloatP)) +BGL_Wrap(3, RasterPos3i, void, (GLint, GLint, GLint)) +BGL_Wrap(1, RasterPos3iv, void, (GLintP)) +BGL_Wrap(3, RasterPos3s, void, (GLshort, GLshort, GLshort)) +BGL_Wrap(1, RasterPos3sv, void, (GLshortP)) +BGL_Wrap(4, RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, RasterPos4dv, void, (GLdoubleP)) +BGL_Wrap(4, RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, RasterPos4fv, void, (GLfloatP)) +BGL_Wrap(4, RasterPos4i, void, (GLint, GLint, GLint, GLint)) +BGL_Wrap(1, RasterPos4iv, void, (GLintP)) +BGL_Wrap(4, RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort)) +BGL_Wrap(1, RasterPos4sv, void, (GLshortP)) +BGL_Wrap(1, ReadBuffer, void, (GLenum)) +BGL_Wrap(7, ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP)) +BGL_Wrap(4, Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(2, Rectdv, void, (GLdoubleP, GLdoubleP)) +BGL_Wrap(4, Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(2, Rectfv, void, (GLfloatP, GLfloatP)) +BGL_Wrap(4, Recti, void, (GLint, GLint, GLint, GLint)) +BGL_Wrap(2, Rectiv, void, (GLintP, GLintP)) +BGL_Wrap(4, Rects, void, (GLshort, GLshort, GLshort, GLshort)) +BGL_Wrap(2, Rectsv, void, (GLshortP, GLshortP)) +BGL_Wrap(1, RenderMode, GLint, (GLenum)) +BGL_Wrap(4, Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(4, Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(3, Scaled, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(3, Scalef, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(4, Scissor, void, (GLint, GLint, GLsizei, GLsizei)) +BGL_Wrap(2, SelectBuffer, void, (GLsizei, GLuintP)) +BGL_Wrap(1, ShadeModel, void, (GLenum)) +BGL_Wrap(3, StencilFunc, void, (GLenum, GLint, GLuint)) +BGL_Wrap(1, StencilMask, void, (GLuint)) +BGL_Wrap(3, StencilOp, void, (GLenum, GLenum, GLenum)) +BGL_Wrap(1, TexCoord1d, void, (GLdouble)) +BGL_Wrap(1, TexCoord1dv, void, (GLdoubleP)) +BGL_Wrap(1, TexCoord1f, void, (GLfloat)) +BGL_Wrap(1, TexCoord1fv, void, (GLfloatP)) +BGL_Wrap(1, TexCoord1i, void, (GLint)) +BGL_Wrap(1, TexCoord1iv, void, (GLintP)) +BGL_Wrap(1, TexCoord1s, void, (GLshort)) +BGL_Wrap(1, TexCoord1sv, void, (GLshortP)) +BGL_Wrap(2, TexCoord2d, void, (GLdouble, GLdouble)) +BGL_Wrap(1, TexCoord2dv, void, (GLdoubleP)) +BGL_Wrap(2, TexCoord2f, void, (GLfloat, GLfloat)) +BGL_Wrap(1, TexCoord2fv, void, (GLfloatP)) +BGL_Wrap(2, TexCoord2i, void, (GLint, GLint)) +BGL_Wrap(1, TexCoord2iv, void, (GLintP)) +BGL_Wrap(2, TexCoord2s, void, (GLshort, GLshort)) +BGL_Wrap(1, TexCoord2sv, void, (GLshortP)) +BGL_Wrap(3, TexCoord3d, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, TexCoord3dv, void, (GLdoubleP)) +BGL_Wrap(3, TexCoord3f, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, TexCoord3fv, void, (GLfloatP)) +BGL_Wrap(3, TexCoord3i, void, (GLint, GLint, GLint)) +BGL_Wrap(1, TexCoord3iv, void, (GLintP)) +BGL_Wrap(3, TexCoord3s, void, (GLshort, GLshort, GLshort)) +BGL_Wrap(1, TexCoord3sv, void, (GLshortP)) +BGL_Wrap(4, TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, TexCoord4dv, void, (GLdoubleP)) +BGL_Wrap(4, TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, TexCoord4fv, void, (GLfloatP)) +BGL_Wrap(4, TexCoord4i, void, (GLint, GLint, GLint, GLint)) +BGL_Wrap(1, TexCoord4iv, void, (GLintP)) +BGL_Wrap(4, TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort)) +BGL_Wrap(1, TexCoord4sv, void, (GLshortP)) +BGL_Wrap(3, TexEnvf, void, (GLenum, GLenum, GLfloat)) +BGL_Wrap(3, TexEnvfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, TexEnvi, void, (GLenum, GLenum, GLint)) +BGL_Wrap(3, TexEnviv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(3, TexGend, void, (GLenum, GLenum, GLdouble)) +BGL_Wrap(3, TexGendv, void, (GLenum, GLenum, GLdoubleP)) +BGL_Wrap(3, TexGenf, void, (GLenum, GLenum, GLfloat)) +BGL_Wrap(3, TexGenfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, TexGeni, void, (GLenum, GLenum, GLint)) +BGL_Wrap(3, TexGeniv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(8, TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP)) +BGL_Wrap(9, TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP)) +BGL_Wrap(3, TexParameterf, void, (GLenum, GLenum, GLfloat)) +BGL_Wrap(3, TexParameterfv, void, (GLenum, GLenum, GLfloatP)) +BGL_Wrap(3, TexParameteri, void, (GLenum, GLenum, GLint)) +BGL_Wrap(3, TexParameteriv, void, (GLenum, GLenum, GLintP)) +BGL_Wrap(3, Translated, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(3, Translatef, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(2, Vertex2d, void, (GLdouble, GLdouble)) +BGL_Wrap(1, Vertex2dv, void, (GLdoubleP)) +BGL_Wrap(2, Vertex2f, void, (GLfloat, GLfloat)) +BGL_Wrap(1, Vertex2fv, void, (GLfloatP)) +BGL_Wrap(2, Vertex2i, void, (GLint, GLint)) +BGL_Wrap(1, Vertex2iv, void, (GLintP)) +BGL_Wrap(2, Vertex2s, void, (GLshort, GLshort)) +BGL_Wrap(1, Vertex2sv, void, (GLshortP)) +BGL_Wrap(3, Vertex3d, void, (GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, Vertex3dv, void, (GLdoubleP)) +BGL_Wrap(3, Vertex3f, void, (GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, Vertex3fv, void, (GLfloatP)) +BGL_Wrap(3, Vertex3i, void, (GLint, GLint, GLint)) +BGL_Wrap(1, Vertex3iv, void, (GLintP)) +BGL_Wrap(3, Vertex3s, void, (GLshort, GLshort, GLshort)) +BGL_Wrap(1, Vertex3sv, void, (GLshortP)) +BGL_Wrap(4, Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble)) +BGL_Wrap(1, Vertex4dv, void, (GLdoubleP)) +BGL_Wrap(4, Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat)) +BGL_Wrap(1, Vertex4fv, void, (GLfloatP)) +BGL_Wrap(4, Vertex4i, void, (GLint, GLint, GLint, GLint)) +BGL_Wrap(1, Vertex4iv, void, (GLintP)) +BGL_Wrap(4, Vertex4s, void, (GLshort, GLshort, GLshort, GLshort)) +BGL_Wrap(1, Vertex4sv, void, (GLshortP)) +BGL_Wrap(4, Viewport, void, (GLint, GLint, GLsizei, GLsizei)) +#endif + +/* XXX */ +#undef MethodDef +#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS} + +static struct PyMethodDef BGL_methods[] = { + {"Buffer", Method_Buffer, METH_VARARGS, Method_Buffer_doc}, +#ifndef __APPLE__ + MethodDef( Accum), + MethodDef( AlphaFunc), + MethodDef( AreTexturesResident), + MethodDef( Begin), + MethodDef( BindTexture), + MethodDef( Bitmap), + MethodDef( BlendFunc), + MethodDef( CallList), + MethodDef( CallLists), + MethodDef( Clear), + MethodDef( ClearAccum), + MethodDef( ClearColor), + MethodDef( ClearDepth), + MethodDef( ClearIndex), + MethodDef( ClearStencil), + MethodDef( ClipPlane), + MethodDef( Color3b), + MethodDef( Color3bv), + MethodDef( Color3d), + MethodDef( Color3dv), + MethodDef( Color3f), + MethodDef( Color3fv), + MethodDef( Color3i), + MethodDef( Color3iv), + MethodDef( Color3s), + MethodDef( Color3sv), + MethodDef( Color3ub), + MethodDef( Color3ubv), + MethodDef( Color3ui), + MethodDef( Color3uiv), + MethodDef( Color3us), + MethodDef( Color3usv), + MethodDef( Color4b), + MethodDef( Color4bv), + MethodDef( Color4d), + MethodDef( Color4dv), + MethodDef( Color4f), + MethodDef( Color4fv), + MethodDef( Color4i), + MethodDef( Color4iv), + MethodDef( Color4s), + MethodDef( Color4sv), + MethodDef( Color4ub), + MethodDef( Color4ubv), + MethodDef( Color4ui), + MethodDef( Color4uiv), + MethodDef( Color4us), + MethodDef( Color4usv), + MethodDef( ColorMask), + MethodDef( ColorMaterial), + MethodDef( CopyPixels), + MethodDef( CullFace), + MethodDef( DeleteLists), + MethodDef( DeleteTextures), + MethodDef( DepthFunc), + MethodDef( DepthMask), + MethodDef( DepthRange), + MethodDef( Disable), + MethodDef( DrawBuffer), + MethodDef( DrawPixels), + MethodDef( EdgeFlag), + MethodDef( EdgeFlagv), + MethodDef( Enable), + MethodDef( End), + MethodDef( EndList), + MethodDef( EvalCoord1d), + MethodDef( EvalCoord1dv), + MethodDef( EvalCoord1f), + MethodDef( EvalCoord1fv), + MethodDef( EvalCoord2d), + MethodDef( EvalCoord2dv), + MethodDef( EvalCoord2f), + MethodDef( EvalCoord2fv), + MethodDef( EvalMesh1), + MethodDef( EvalMesh2), + MethodDef( EvalPoint1), + MethodDef( EvalPoint2), + MethodDef( FeedbackBuffer), + MethodDef( Finish), + MethodDef( Flush), + MethodDef( Fogf), + MethodDef( Fogfv), + MethodDef( Fogi), + MethodDef( Fogiv), + MethodDef( FrontFace), + MethodDef( Frustum), + MethodDef( GenLists), + MethodDef( GenTextures), + MethodDef( GetBooleanv), + MethodDef( GetClipPlane), + MethodDef( GetDoublev), + MethodDef( GetError), + MethodDef( GetFloatv), + MethodDef( GetIntegerv), + MethodDef( GetLightfv), + MethodDef( GetLightiv), + MethodDef( GetMapdv), + MethodDef( GetMapfv), + MethodDef( GetMapiv), + MethodDef( GetMaterialfv), + MethodDef( GetMaterialiv), + MethodDef( GetPixelMapfv), + MethodDef( GetPixelMapuiv), + MethodDef( GetPixelMapusv), + MethodDef( GetPolygonStipple), + MethodDef( GetString), + MethodDef( GetTexEnvfv), + MethodDef( GetTexEnviv), + MethodDef( GetTexGendv), + MethodDef( GetTexGenfv), + MethodDef( GetTexGeniv), + MethodDef( GetTexImage), + MethodDef( GetTexLevelParameterfv), + MethodDef( GetTexLevelParameteriv), + MethodDef( GetTexParameterfv), + MethodDef( GetTexParameteriv), + MethodDef( Hint), + MethodDef( IndexMask), + MethodDef( Indexd), + MethodDef( Indexdv), + MethodDef( Indexf), + MethodDef( Indexfv), + MethodDef( Indexi), + MethodDef( Indexiv), + MethodDef( Indexs), + MethodDef( Indexsv), + MethodDef( InitNames), + MethodDef( IsEnabled), + MethodDef( IsList), + MethodDef( IsTexture), + MethodDef( LightModelf), + MethodDef( LightModelfv), + MethodDef( LightModeli), + MethodDef( LightModeliv), + MethodDef( Lightf), + MethodDef( Lightfv), + MethodDef( Lighti), + MethodDef( Lightiv), + MethodDef( LineStipple), + MethodDef( LineWidth), + MethodDef( ListBase), + MethodDef( LoadIdentity), + MethodDef( LoadMatrixd), + MethodDef( LoadMatrixf), + MethodDef( LoadName), + MethodDef( LogicOp), + MethodDef( Map1d), + MethodDef( Map1f), + MethodDef( Map2d), + MethodDef( Map2f), + MethodDef( MapGrid1d), + MethodDef( MapGrid1f), + MethodDef( MapGrid2d), + MethodDef( MapGrid2f), + MethodDef( Materialf), + MethodDef( Materialfv), + MethodDef( Materiali), + MethodDef( Materialiv), + MethodDef( MatrixMode), + MethodDef( MultMatrixd), + MethodDef( MultMatrixf), + MethodDef( NewList), + MethodDef( Normal3b), + MethodDef( Normal3bv), + MethodDef( Normal3d), + MethodDef( Normal3dv), + MethodDef( Normal3f), + MethodDef( Normal3fv), + MethodDef( Normal3i), + MethodDef( Normal3iv), + MethodDef( Normal3s), + MethodDef( Normal3sv), + MethodDef( Ortho), + MethodDef( PassThrough), + MethodDef( PixelMapfv), + MethodDef( PixelMapuiv), + MethodDef( PixelMapusv), + MethodDef( PixelStoref), + MethodDef( PixelStorei), + MethodDef( PixelTransferf), + MethodDef( PixelTransferi), + MethodDef( PixelZoom), + MethodDef( PointSize), + MethodDef( PolygonMode), + MethodDef( PolygonOffset), + MethodDef( PolygonStipple), + MethodDef( PopAttrib), + MethodDef( PopMatrix), + MethodDef( PopName), + MethodDef( PrioritizeTextures), + MethodDef( PushAttrib), + MethodDef( PushMatrix), + MethodDef( PushName), + MethodDef( RasterPos2d), + MethodDef( RasterPos2dv), + MethodDef( RasterPos2f), + MethodDef( RasterPos2fv), + MethodDef( RasterPos2i), + MethodDef( RasterPos2iv), + MethodDef( RasterPos2s), + MethodDef( RasterPos2sv), + MethodDef( RasterPos3d), + MethodDef( RasterPos3dv), + MethodDef( RasterPos3f), + MethodDef( RasterPos3fv), + MethodDef( RasterPos3i), + MethodDef( RasterPos3iv), + MethodDef( RasterPos3s), + MethodDef( RasterPos3sv), + MethodDef( RasterPos4d), + MethodDef( RasterPos4dv), + MethodDef( RasterPos4f), + MethodDef( RasterPos4fv), + MethodDef( RasterPos4i), + MethodDef( RasterPos4iv), + MethodDef( RasterPos4s), + MethodDef( RasterPos4sv), + MethodDef( ReadBuffer), + MethodDef( ReadPixels), + MethodDef( Rectd), + MethodDef( Rectdv), + MethodDef( Rectf), + MethodDef( Rectfv), + MethodDef( Recti), + MethodDef( Rectiv), + MethodDef( Rects), + MethodDef( Rectsv), + MethodDef( RenderMode), + MethodDef( Rotated), + MethodDef( Rotatef), + MethodDef( Scaled), + MethodDef( Scalef), + MethodDef( Scissor), + MethodDef( SelectBuffer), + MethodDef( ShadeModel), + MethodDef( StencilFunc), + MethodDef( StencilMask), + MethodDef( StencilOp), + MethodDef( TexCoord1d), + MethodDef( TexCoord1dv), + MethodDef( TexCoord1f), + MethodDef( TexCoord1fv), + MethodDef( TexCoord1i), + MethodDef( TexCoord1iv), + MethodDef( TexCoord1s), + MethodDef( TexCoord1sv), + MethodDef( TexCoord2d), + MethodDef( TexCoord2dv), + MethodDef( TexCoord2f), + MethodDef( TexCoord2fv), + MethodDef( TexCoord2i), + MethodDef( TexCoord2iv), + MethodDef( TexCoord2s), + MethodDef( TexCoord2sv), + MethodDef( TexCoord3d), + MethodDef( TexCoord3dv), + MethodDef( TexCoord3f), + MethodDef( TexCoord3fv), + MethodDef( TexCoord3i), + MethodDef( TexCoord3iv), + MethodDef( TexCoord3s), + MethodDef( TexCoord3sv), + MethodDef( TexCoord4d), + MethodDef( TexCoord4dv), + MethodDef( TexCoord4f), + MethodDef( TexCoord4fv), + MethodDef( TexCoord4i), + MethodDef( TexCoord4iv), + MethodDef( TexCoord4s), + MethodDef( TexCoord4sv), + MethodDef( TexEnvf), + MethodDef( TexEnvfv), + MethodDef( TexEnvi), + MethodDef( TexEnviv), + MethodDef( TexGend), + MethodDef( TexGendv), + MethodDef( TexGenf), + MethodDef( TexGenfv), + MethodDef( TexGeni), + MethodDef( TexGeniv), + MethodDef( TexImage1D), + MethodDef( TexImage2D), + MethodDef( TexParameterf), + MethodDef( TexParameterfv), + MethodDef( TexParameteri), + MethodDef( TexParameteriv), + MethodDef( Translated), + MethodDef( Translatef), + MethodDef( Vertex2d), + MethodDef( Vertex2dv), + MethodDef( Vertex2f), + MethodDef( Vertex2fv), + MethodDef( Vertex2i), + MethodDef( Vertex2iv), + MethodDef( Vertex2s), + MethodDef( Vertex2sv), + MethodDef( Vertex3d), + MethodDef( Vertex3dv), + MethodDef( Vertex3f), + MethodDef( Vertex3fv), + MethodDef( Vertex3i), + MethodDef( Vertex3iv), + MethodDef( Vertex3s), + MethodDef( Vertex3sv), + MethodDef( Vertex4d), + MethodDef( Vertex4dv), + MethodDef( Vertex4f), + MethodDef( Vertex4fv), + MethodDef( Vertex4i), + MethodDef( Vertex4iv), + MethodDef( Vertex4s), + MethodDef( Vertex4sv), + MethodDef( Viewport), +#endif + + {NULL, NULL} +}; + +PyObject *init_py_bgl(void) +{ + PyObject *mod= Py_InitModule(SUBMODULE(BGL), BGL_methods); + PyObject *dict= PyModule_GetDict(mod); + + Buffer_Type.ob_type= &PyType_Type; + + BPY_ADDCONST(dict, GL_CURRENT_BIT); + BPY_ADDCONST(dict, GL_POINT_BIT); + BPY_ADDCONST(dict, GL_LINE_BIT); + BPY_ADDCONST(dict, GL_POLYGON_BIT); + BPY_ADDCONST(dict, GL_POLYGON_STIPPLE_BIT); + BPY_ADDCONST(dict, GL_PIXEL_MODE_BIT); + BPY_ADDCONST(dict, GL_LIGHTING_BIT); + BPY_ADDCONST(dict, GL_FOG_BIT); + BPY_ADDCONST(dict, GL_DEPTH_BUFFER_BIT); + BPY_ADDCONST(dict, GL_ACCUM_BUFFER_BIT); + BPY_ADDCONST(dict, GL_STENCIL_BUFFER_BIT); + BPY_ADDCONST(dict, GL_VIEWPORT_BIT); + BPY_ADDCONST(dict, GL_TRANSFORM_BIT); + BPY_ADDCONST(dict, GL_ENABLE_BIT); + BPY_ADDCONST(dict, GL_COLOR_BUFFER_BIT); + BPY_ADDCONST(dict, GL_HINT_BIT); + BPY_ADDCONST(dict, GL_EVAL_BIT); + BPY_ADDCONST(dict, GL_LIST_BIT); + BPY_ADDCONST(dict, GL_TEXTURE_BIT); + BPY_ADDCONST(dict, GL_SCISSOR_BIT); + BPY_ADDCONST(dict, GL_ALL_ATTRIB_BITS); + + BPY_ADDCONST(dict, GL_FALSE); + BPY_ADDCONST(dict, GL_TRUE); + + BPY_ADDCONST(dict, GL_POINTS); + BPY_ADDCONST(dict, GL_LINES); + BPY_ADDCONST(dict, GL_LINE_LOOP); + BPY_ADDCONST(dict, GL_LINE_STRIP); + BPY_ADDCONST(dict, GL_TRIANGLES); + BPY_ADDCONST(dict, GL_TRIANGLE_STRIP); + BPY_ADDCONST(dict, GL_TRIANGLE_FAN); + BPY_ADDCONST(dict, GL_QUADS); + BPY_ADDCONST(dict, GL_QUAD_STRIP); + BPY_ADDCONST(dict, GL_POLYGON); + + BPY_ADDCONST(dict, GL_ACCUM); + BPY_ADDCONST(dict, GL_LOAD); + BPY_ADDCONST(dict, GL_RETURN); + BPY_ADDCONST(dict, GL_MULT); + BPY_ADDCONST(dict, GL_ADD); + + BPY_ADDCONST(dict, GL_NEVER); + BPY_ADDCONST(dict, GL_LESS); + BPY_ADDCONST(dict, GL_EQUAL); + BPY_ADDCONST(dict, GL_LEQUAL); + BPY_ADDCONST(dict, GL_GREATER); + BPY_ADDCONST(dict, GL_NOTEQUAL); + BPY_ADDCONST(dict, GL_GEQUAL); + BPY_ADDCONST(dict, GL_ALWAYS); + + BPY_ADDCONST(dict, GL_ZERO); + BPY_ADDCONST(dict, GL_ONE); + BPY_ADDCONST(dict, GL_SRC_COLOR); + BPY_ADDCONST(dict, GL_ONE_MINUS_SRC_COLOR); + BPY_ADDCONST(dict, GL_SRC_ALPHA); + BPY_ADDCONST(dict, GL_ONE_MINUS_SRC_ALPHA); + BPY_ADDCONST(dict, GL_DST_ALPHA); + BPY_ADDCONST(dict, GL_ONE_MINUS_DST_ALPHA); + + BPY_ADDCONST(dict, GL_DST_COLOR); + BPY_ADDCONST(dict, GL_ONE_MINUS_DST_COLOR); + BPY_ADDCONST(dict, GL_SRC_ALPHA_SATURATE); + + BPY_ADDCONST(dict, GL_NONE); + BPY_ADDCONST(dict, GL_FRONT_LEFT); + BPY_ADDCONST(dict, GL_FRONT_RIGHT); + BPY_ADDCONST(dict, GL_BACK_LEFT); + BPY_ADDCONST(dict, GL_BACK_RIGHT); + BPY_ADDCONST(dict, GL_FRONT); + BPY_ADDCONST(dict, GL_BACK); + BPY_ADDCONST(dict, GL_LEFT); + BPY_ADDCONST(dict, GL_RIGHT); + BPY_ADDCONST(dict, GL_FRONT_AND_BACK); + BPY_ADDCONST(dict, GL_AUX0); + BPY_ADDCONST(dict, GL_AUX1); + BPY_ADDCONST(dict, GL_AUX2); + BPY_ADDCONST(dict, GL_AUX3); + + BPY_ADDCONST(dict, GL_NO_ERROR); + BPY_ADDCONST(dict, GL_INVALID_ENUM); + BPY_ADDCONST(dict, GL_INVALID_VALUE); + BPY_ADDCONST(dict, GL_INVALID_OPERATION); + BPY_ADDCONST(dict, GL_STACK_OVERFLOW); + BPY_ADDCONST(dict, GL_STACK_UNDERFLOW); + BPY_ADDCONST(dict, GL_OUT_OF_MEMORY); + + BPY_ADDCONST(dict, GL_2D); + BPY_ADDCONST(dict, GL_3D); + BPY_ADDCONST(dict, GL_3D_COLOR); + BPY_ADDCONST(dict, GL_3D_COLOR_TEXTURE); + BPY_ADDCONST(dict, GL_4D_COLOR_TEXTURE); + + BPY_ADDCONST(dict, GL_PASS_THROUGH_TOKEN); + BPY_ADDCONST(dict, GL_POINT_TOKEN); + BPY_ADDCONST(dict, GL_LINE_TOKEN); + BPY_ADDCONST(dict, GL_POLYGON_TOKEN); + BPY_ADDCONST(dict, GL_BITMAP_TOKEN); + BPY_ADDCONST(dict, GL_DRAW_PIXEL_TOKEN); + BPY_ADDCONST(dict, GL_COPY_PIXEL_TOKEN); + BPY_ADDCONST(dict, GL_LINE_RESET_TOKEN); + + BPY_ADDCONST(dict, GL_EXP); + BPY_ADDCONST(dict, GL_EXP2); + + BPY_ADDCONST(dict, GL_CW); + BPY_ADDCONST(dict, GL_CCW); + + BPY_ADDCONST(dict, GL_COEFF); + BPY_ADDCONST(dict, GL_ORDER); + BPY_ADDCONST(dict, GL_DOMAIN); + + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_I); + BPY_ADDCONST(dict, GL_PIXEL_MAP_S_TO_S); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_R); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_G); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_B); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_A); + BPY_ADDCONST(dict, GL_PIXEL_MAP_R_TO_R); + BPY_ADDCONST(dict, GL_PIXEL_MAP_G_TO_G); + BPY_ADDCONST(dict, GL_PIXEL_MAP_B_TO_B); + BPY_ADDCONST(dict, GL_PIXEL_MAP_A_TO_A); + + BPY_ADDCONST(dict, GL_CURRENT_COLOR); + BPY_ADDCONST(dict, GL_CURRENT_INDEX); + BPY_ADDCONST(dict, GL_CURRENT_NORMAL); + BPY_ADDCONST(dict, GL_CURRENT_TEXTURE_COORDS); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_COLOR); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_INDEX); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_TEXTURE_COORDS); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_POSITION); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_POSITION_VALID); + BPY_ADDCONST(dict, GL_CURRENT_RASTER_DISTANCE); + BPY_ADDCONST(dict, GL_POINT_SMOOTH); + BPY_ADDCONST(dict, GL_POINT_SIZE); + BPY_ADDCONST(dict, GL_POINT_SIZE_RANGE); + BPY_ADDCONST(dict, GL_POINT_SIZE_GRANULARITY); + BPY_ADDCONST(dict, GL_LINE_SMOOTH); + BPY_ADDCONST(dict, GL_LINE_WIDTH); + BPY_ADDCONST(dict, GL_LINE_WIDTH_RANGE); + BPY_ADDCONST(dict, GL_LINE_WIDTH_GRANULARITY); + BPY_ADDCONST(dict, GL_LINE_STIPPLE); + BPY_ADDCONST(dict, GL_LINE_STIPPLE_PATTERN); + BPY_ADDCONST(dict, GL_LINE_STIPPLE_REPEAT); + BPY_ADDCONST(dict, GL_LIST_MODE); + BPY_ADDCONST(dict, GL_MAX_LIST_NESTING); + BPY_ADDCONST(dict, GL_LIST_BASE); + BPY_ADDCONST(dict, GL_LIST_INDEX); + BPY_ADDCONST(dict, GL_POLYGON_MODE); + BPY_ADDCONST(dict, GL_POLYGON_SMOOTH); + BPY_ADDCONST(dict, GL_POLYGON_STIPPLE); + BPY_ADDCONST(dict, GL_EDGE_FLAG); + BPY_ADDCONST(dict, GL_CULL_FACE); + BPY_ADDCONST(dict, GL_CULL_FACE_MODE); + BPY_ADDCONST(dict, GL_FRONT_FACE); + BPY_ADDCONST(dict, GL_LIGHTING); + BPY_ADDCONST(dict, GL_LIGHT_MODEL_LOCAL_VIEWER); + BPY_ADDCONST(dict, GL_LIGHT_MODEL_TWO_SIDE); + BPY_ADDCONST(dict, GL_LIGHT_MODEL_AMBIENT); + BPY_ADDCONST(dict, GL_SHADE_MODEL); + BPY_ADDCONST(dict, GL_COLOR_MATERIAL_FACE); + BPY_ADDCONST(dict, GL_COLOR_MATERIAL_PARAMETER); + BPY_ADDCONST(dict, GL_COLOR_MATERIAL); + BPY_ADDCONST(dict, GL_FOG); + BPY_ADDCONST(dict, GL_FOG_INDEX); + BPY_ADDCONST(dict, GL_FOG_DENSITY); + BPY_ADDCONST(dict, GL_FOG_START); + BPY_ADDCONST(dict, GL_FOG_END); + BPY_ADDCONST(dict, GL_FOG_MODE); + BPY_ADDCONST(dict, GL_FOG_COLOR); + BPY_ADDCONST(dict, GL_DEPTH_RANGE); + BPY_ADDCONST(dict, GL_DEPTH_TEST); + BPY_ADDCONST(dict, GL_DEPTH_WRITEMASK); + BPY_ADDCONST(dict, GL_DEPTH_CLEAR_VALUE); + BPY_ADDCONST(dict, GL_DEPTH_FUNC); + BPY_ADDCONST(dict, GL_ACCUM_CLEAR_VALUE); + BPY_ADDCONST(dict, GL_STENCIL_TEST); + BPY_ADDCONST(dict, GL_STENCIL_CLEAR_VALUE); + BPY_ADDCONST(dict, GL_STENCIL_FUNC); + BPY_ADDCONST(dict, GL_STENCIL_VALUE_MASK); + BPY_ADDCONST(dict, GL_STENCIL_FAIL); + BPY_ADDCONST(dict, GL_STENCIL_PASS_DEPTH_FAIL); + BPY_ADDCONST(dict, GL_STENCIL_PASS_DEPTH_PASS); + BPY_ADDCONST(dict, GL_STENCIL_REF); + BPY_ADDCONST(dict, GL_STENCIL_WRITEMASK); + BPY_ADDCONST(dict, GL_MATRIX_MODE); + BPY_ADDCONST(dict, GL_NORMALIZE); + BPY_ADDCONST(dict, GL_VIEWPORT); + BPY_ADDCONST(dict, GL_MODELVIEW_STACK_DEPTH); + BPY_ADDCONST(dict, GL_PROJECTION_STACK_DEPTH); + BPY_ADDCONST(dict, GL_TEXTURE_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MODELVIEW_MATRIX); + BPY_ADDCONST(dict, GL_PROJECTION_MATRIX); + BPY_ADDCONST(dict, GL_TEXTURE_MATRIX); + BPY_ADDCONST(dict, GL_ATTRIB_STACK_DEPTH); + BPY_ADDCONST(dict, GL_ALPHA_TEST); + BPY_ADDCONST(dict, GL_ALPHA_TEST_FUNC); + BPY_ADDCONST(dict, GL_ALPHA_TEST_REF); + BPY_ADDCONST(dict, GL_DITHER); + BPY_ADDCONST(dict, GL_BLEND_DST); + BPY_ADDCONST(dict, GL_BLEND_SRC); + BPY_ADDCONST(dict, GL_BLEND); + BPY_ADDCONST(dict, GL_LOGIC_OP_MODE); + BPY_ADDCONST(dict, GL_LOGIC_OP); + BPY_ADDCONST(dict, GL_AUX_BUFFERS); + BPY_ADDCONST(dict, GL_DRAW_BUFFER); + BPY_ADDCONST(dict, GL_READ_BUFFER); + BPY_ADDCONST(dict, GL_SCISSOR_BOX); + BPY_ADDCONST(dict, GL_SCISSOR_TEST); + BPY_ADDCONST(dict, GL_INDEX_CLEAR_VALUE); + BPY_ADDCONST(dict, GL_INDEX_WRITEMASK); + BPY_ADDCONST(dict, GL_COLOR_CLEAR_VALUE); + BPY_ADDCONST(dict, GL_COLOR_WRITEMASK); + BPY_ADDCONST(dict, GL_INDEX_MODE); + BPY_ADDCONST(dict, GL_RGBA_MODE); + BPY_ADDCONST(dict, GL_DOUBLEBUFFER); + BPY_ADDCONST(dict, GL_STEREO); + BPY_ADDCONST(dict, GL_RENDER_MODE); + BPY_ADDCONST(dict, GL_PERSPECTIVE_CORRECTION_HINT); + BPY_ADDCONST(dict, GL_POINT_SMOOTH_HINT); + BPY_ADDCONST(dict, GL_LINE_SMOOTH_HINT); + BPY_ADDCONST(dict, GL_POLYGON_SMOOTH_HINT); + BPY_ADDCONST(dict, GL_FOG_HINT); + BPY_ADDCONST(dict, GL_TEXTURE_GEN_S); + BPY_ADDCONST(dict, GL_TEXTURE_GEN_T); + BPY_ADDCONST(dict, GL_TEXTURE_GEN_R); + BPY_ADDCONST(dict, GL_TEXTURE_GEN_Q); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_I_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_S_TO_S_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_R_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_G_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_B_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_I_TO_A_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_R_TO_R_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_G_TO_G_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_B_TO_B_SIZE); + BPY_ADDCONST(dict, GL_PIXEL_MAP_A_TO_A_SIZE); + BPY_ADDCONST(dict, GL_UNPACK_SWAP_BYTES); + BPY_ADDCONST(dict, GL_UNPACK_LSB_FIRST); + BPY_ADDCONST(dict, GL_UNPACK_ROW_LENGTH); + BPY_ADDCONST(dict, GL_UNPACK_SKIP_ROWS); + BPY_ADDCONST(dict, GL_UNPACK_SKIP_PIXELS); + BPY_ADDCONST(dict, GL_UNPACK_ALIGNMENT); + BPY_ADDCONST(dict, GL_PACK_SWAP_BYTES); + BPY_ADDCONST(dict, GL_PACK_LSB_FIRST); + BPY_ADDCONST(dict, GL_PACK_ROW_LENGTH); + BPY_ADDCONST(dict, GL_PACK_SKIP_ROWS); + BPY_ADDCONST(dict, GL_PACK_SKIP_PIXELS); + BPY_ADDCONST(dict, GL_PACK_ALIGNMENT); + BPY_ADDCONST(dict, GL_MAP_COLOR); + BPY_ADDCONST(dict, GL_MAP_STENCIL); + BPY_ADDCONST(dict, GL_INDEX_SHIFT); + BPY_ADDCONST(dict, GL_INDEX_OFFSET); + BPY_ADDCONST(dict, GL_RED_SCALE); + BPY_ADDCONST(dict, GL_RED_BIAS); + BPY_ADDCONST(dict, GL_ZOOM_X); + BPY_ADDCONST(dict, GL_ZOOM_Y); + BPY_ADDCONST(dict, GL_GREEN_SCALE); + BPY_ADDCONST(dict, GL_GREEN_BIAS); + BPY_ADDCONST(dict, GL_BLUE_SCALE); + BPY_ADDCONST(dict, GL_BLUE_BIAS); + BPY_ADDCONST(dict, GL_ALPHA_SCALE); + BPY_ADDCONST(dict, GL_ALPHA_BIAS); + BPY_ADDCONST(dict, GL_DEPTH_SCALE); + BPY_ADDCONST(dict, GL_DEPTH_BIAS); + BPY_ADDCONST(dict, GL_MAX_EVAL_ORDER); + BPY_ADDCONST(dict, GL_MAX_LIGHTS); + BPY_ADDCONST(dict, GL_MAX_CLIP_PLANES); + BPY_ADDCONST(dict, GL_MAX_TEXTURE_SIZE); + BPY_ADDCONST(dict, GL_MAX_PIXEL_MAP_TABLE); + BPY_ADDCONST(dict, GL_MAX_ATTRIB_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MAX_MODELVIEW_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MAX_NAME_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MAX_PROJECTION_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MAX_TEXTURE_STACK_DEPTH); + BPY_ADDCONST(dict, GL_MAX_VIEWPORT_DIMS); + BPY_ADDCONST(dict, GL_SUBPIXEL_BITS); + BPY_ADDCONST(dict, GL_INDEX_BITS); + BPY_ADDCONST(dict, GL_RED_BITS); + BPY_ADDCONST(dict, GL_GREEN_BITS); + BPY_ADDCONST(dict, GL_BLUE_BITS); + BPY_ADDCONST(dict, GL_ALPHA_BITS); + BPY_ADDCONST(dict, GL_DEPTH_BITS); + BPY_ADDCONST(dict, GL_STENCIL_BITS); + BPY_ADDCONST(dict, GL_ACCUM_RED_BITS); + BPY_ADDCONST(dict, GL_ACCUM_GREEN_BITS); + BPY_ADDCONST(dict, GL_ACCUM_BLUE_BITS); + BPY_ADDCONST(dict, GL_ACCUM_ALPHA_BITS); + BPY_ADDCONST(dict, GL_NAME_STACK_DEPTH); + BPY_ADDCONST(dict, GL_AUTO_NORMAL); + BPY_ADDCONST(dict, GL_MAP1_COLOR_4); + BPY_ADDCONST(dict, GL_MAP1_INDEX); + BPY_ADDCONST(dict, GL_MAP1_NORMAL); + BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_1); + BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_2); + BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_3); + BPY_ADDCONST(dict, GL_MAP1_TEXTURE_COORD_4); + BPY_ADDCONST(dict, GL_MAP1_VERTEX_3); + BPY_ADDCONST(dict, GL_MAP1_VERTEX_4); + BPY_ADDCONST(dict, GL_MAP2_COLOR_4); + BPY_ADDCONST(dict, GL_MAP2_INDEX); + BPY_ADDCONST(dict, GL_MAP2_NORMAL); + BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_1); + BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_2); + BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_3); + BPY_ADDCONST(dict, GL_MAP2_TEXTURE_COORD_4); + BPY_ADDCONST(dict, GL_MAP2_VERTEX_3); + BPY_ADDCONST(dict, GL_MAP2_VERTEX_4); + BPY_ADDCONST(dict, GL_MAP1_GRID_DOMAIN); + BPY_ADDCONST(dict, GL_MAP1_GRID_SEGMENTS); + BPY_ADDCONST(dict, GL_MAP2_GRID_DOMAIN); + BPY_ADDCONST(dict, GL_MAP2_GRID_SEGMENTS); + BPY_ADDCONST(dict, GL_TEXTURE_1D); + BPY_ADDCONST(dict, GL_TEXTURE_2D); + + BPY_ADDCONST(dict, GL_TEXTURE_WIDTH); + BPY_ADDCONST(dict, GL_TEXTURE_HEIGHT); + BPY_ADDCONST(dict, GL_TEXTURE_COMPONENTS); + BPY_ADDCONST(dict, GL_TEXTURE_BORDER_COLOR); + BPY_ADDCONST(dict, GL_TEXTURE_BORDER); + + BPY_ADDCONST(dict, GL_DONT_CARE); + BPY_ADDCONST(dict, GL_FASTEST); + BPY_ADDCONST(dict, GL_NICEST); + + BPY_ADDCONST(dict, GL_AMBIENT); + BPY_ADDCONST(dict, GL_DIFFUSE); + BPY_ADDCONST(dict, GL_SPECULAR); + BPY_ADDCONST(dict, GL_POSITION); + BPY_ADDCONST(dict, GL_SPOT_DIRECTION); + BPY_ADDCONST(dict, GL_SPOT_EXPONENT); + BPY_ADDCONST(dict, GL_SPOT_CUTOFF); + BPY_ADDCONST(dict, GL_CONSTANT_ATTENUATION); + BPY_ADDCONST(dict, GL_LINEAR_ATTENUATION); + BPY_ADDCONST(dict, GL_QUADRATIC_ATTENUATION); + + BPY_ADDCONST(dict, GL_COMPILE); + BPY_ADDCONST(dict, GL_COMPILE_AND_EXECUTE); + + BPY_ADDCONST(dict, GL_BYTE); + BPY_ADDCONST(dict, GL_UNSIGNED_BYTE); + BPY_ADDCONST(dict, GL_SHORT); + BPY_ADDCONST(dict, GL_UNSIGNED_SHORT); + BPY_ADDCONST(dict, GL_INT); + BPY_ADDCONST(dict, GL_UNSIGNED_INT); + BPY_ADDCONST(dict, GL_FLOAT); + BPY_ADDCONST(dict, GL_2_BYTES); + BPY_ADDCONST(dict, GL_3_BYTES); + BPY_ADDCONST(dict, GL_4_BYTES); + + BPY_ADDCONST(dict, GL_CLEAR); + BPY_ADDCONST(dict, GL_AND); + BPY_ADDCONST(dict, GL_AND_REVERSE); + BPY_ADDCONST(dict, GL_COPY); + BPY_ADDCONST(dict, GL_AND_INVERTED); + BPY_ADDCONST(dict, GL_NOOP); + BPY_ADDCONST(dict, GL_XOR); + BPY_ADDCONST(dict, GL_OR); + BPY_ADDCONST(dict, GL_NOR); + BPY_ADDCONST(dict, GL_EQUIV); + BPY_ADDCONST(dict, GL_INVERT); + BPY_ADDCONST(dict, GL_OR_REVERSE); + BPY_ADDCONST(dict, GL_COPY_INVERTED); + BPY_ADDCONST(dict, GL_OR_INVERTED); + BPY_ADDCONST(dict, GL_NAND); + BPY_ADDCONST(dict, GL_SET); + + BPY_ADDCONST(dict, GL_EMISSION); + BPY_ADDCONST(dict, GL_SHININESS); + BPY_ADDCONST(dict, GL_AMBIENT_AND_DIFFUSE); + BPY_ADDCONST(dict, GL_COLOR_INDEXES); + + BPY_ADDCONST(dict, GL_MODELVIEW); + BPY_ADDCONST(dict, GL_PROJECTION); + BPY_ADDCONST(dict, GL_TEXTURE); + + BPY_ADDCONST(dict, GL_COLOR); + BPY_ADDCONST(dict, GL_DEPTH); + BPY_ADDCONST(dict, GL_STENCIL); + + BPY_ADDCONST(dict, GL_COLOR_INDEX); + BPY_ADDCONST(dict, GL_STENCIL_INDEX); + BPY_ADDCONST(dict, GL_DEPTH_COMPONENT); + BPY_ADDCONST(dict, GL_RED); + BPY_ADDCONST(dict, GL_GREEN); + BPY_ADDCONST(dict, GL_BLUE); + BPY_ADDCONST(dict, GL_ALPHA); + BPY_ADDCONST(dict, GL_RGB); + BPY_ADDCONST(dict, GL_RGBA); + BPY_ADDCONST(dict, GL_LUMINANCE); + BPY_ADDCONST(dict, GL_LUMINANCE_ALPHA); + + BPY_ADDCONST(dict, GL_BITMAP); + + BPY_ADDCONST(dict, GL_POINT); + BPY_ADDCONST(dict, GL_LINE); + BPY_ADDCONST(dict, GL_FILL); + + BPY_ADDCONST(dict, GL_RENDER); + BPY_ADDCONST(dict, GL_FEEDBACK); + BPY_ADDCONST(dict, GL_SELECT); + + BPY_ADDCONST(dict, GL_FLAT); + BPY_ADDCONST(dict, GL_SMOOTH); + + BPY_ADDCONST(dict, GL_KEEP); + BPY_ADDCONST(dict, GL_REPLACE); + BPY_ADDCONST(dict, GL_INCR); + BPY_ADDCONST(dict, GL_DECR); + + BPY_ADDCONST(dict, GL_VENDOR); + BPY_ADDCONST(dict, GL_RENDERER); + BPY_ADDCONST(dict, GL_VERSION); + BPY_ADDCONST(dict, GL_EXTENSIONS); + + BPY_ADDCONST(dict, GL_S); + BPY_ADDCONST(dict, GL_T); + BPY_ADDCONST(dict, GL_R); + BPY_ADDCONST(dict, GL_Q); + + BPY_ADDCONST(dict, GL_MODULATE); + BPY_ADDCONST(dict, GL_DECAL); + + BPY_ADDCONST(dict, GL_TEXTURE_ENV_MODE); + BPY_ADDCONST(dict, GL_TEXTURE_ENV_COLOR); + + BPY_ADDCONST(dict, GL_TEXTURE_ENV); + + BPY_ADDCONST(dict, GL_EYE_LINEAR); + BPY_ADDCONST(dict, GL_OBJECT_LINEAR); + BPY_ADDCONST(dict, GL_SPHERE_MAP); + + BPY_ADDCONST(dict, GL_TEXTURE_GEN_MODE); + BPY_ADDCONST(dict, GL_OBJECT_PLANE); + BPY_ADDCONST(dict, GL_EYE_PLANE); + + BPY_ADDCONST(dict, GL_NEAREST); + BPY_ADDCONST(dict, GL_LINEAR); + + BPY_ADDCONST(dict, GL_NEAREST_MIPMAP_NEAREST); + BPY_ADDCONST(dict, GL_LINEAR_MIPMAP_NEAREST); + BPY_ADDCONST(dict, GL_NEAREST_MIPMAP_LINEAR); + BPY_ADDCONST(dict, GL_LINEAR_MIPMAP_LINEAR); + + BPY_ADDCONST(dict, GL_TEXTURE_MAG_FILTER); + BPY_ADDCONST(dict, GL_TEXTURE_MIN_FILTER); + BPY_ADDCONST(dict, GL_TEXTURE_WRAP_S); + BPY_ADDCONST(dict, GL_TEXTURE_WRAP_T); + + BPY_ADDCONST(dict, GL_CLAMP); + BPY_ADDCONST(dict, GL_REPEAT); + + BPY_ADDCONST(dict, GL_CLIP_PLANE0); + BPY_ADDCONST(dict, GL_CLIP_PLANE1); + BPY_ADDCONST(dict, GL_CLIP_PLANE2); + BPY_ADDCONST(dict, GL_CLIP_PLANE3); + BPY_ADDCONST(dict, GL_CLIP_PLANE4); + BPY_ADDCONST(dict, GL_CLIP_PLANE5); + + BPY_ADDCONST(dict, GL_LIGHT0); + BPY_ADDCONST(dict, GL_LIGHT1); + BPY_ADDCONST(dict, GL_LIGHT2); + BPY_ADDCONST(dict, GL_LIGHT3); + BPY_ADDCONST(dict, GL_LIGHT4); + BPY_ADDCONST(dict, GL_LIGHT5); + BPY_ADDCONST(dict, GL_LIGHT6); + BPY_ADDCONST(dict, GL_LIGHT7); + + BPY_ADDCONST(dict, GL_POLYGON_OFFSET_UNITS); + BPY_ADDCONST(dict, GL_POLYGON_OFFSET_POINT); + BPY_ADDCONST(dict, GL_POLYGON_OFFSET_LINE); + BPY_ADDCONST(dict, GL_POLYGON_OFFSET_FILL); + BPY_ADDCONST(dict, GL_POLYGON_OFFSET_FACTOR); + + BPY_ADDCONST(dict, GL_TEXTURE_PRIORITY); + BPY_ADDCONST(dict, GL_TEXTURE_RESIDENT); + BPY_ADDCONST(dict, GL_TEXTURE_BINDING_1D); + BPY_ADDCONST(dict, GL_TEXTURE_BINDING_2D); + + return mod; +} + +void initDraw(void) +{ + init_py_draw(); + init_py_bgl(); +} diff --git a/source/blender/bpython/intern/opy_matrix.c b/source/blender/bpython/intern/opy_matrix.c new file mode 100644 index 00000000000..cd93bd5f311 --- /dev/null +++ b/source/blender/bpython/intern/opy_matrix.c @@ -0,0 +1,173 @@ +/* python.c MIXED MODEL + * + * june 99 + * $Id$ + * + * this code might die... + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "BPY_tools.h" +#include "BPY_macros.h" + +#include "BLI_arithb.h" +#include "opy_vector.h" + +PyObject *BPY_tuple_repr(PyObject *self, int size); + +/* PROTOS */ +// PyObject *newVectorObject(float *vec, int size); + +/*****************************/ +/* Matrix Python Object */ +/*****************************/ + + +#define GETROWVECTOR(mat, i) ( (float *) mat[i]) + +static void Matrix_dealloc(MatrixObject *self) { + Py_DECREF(self->rows[0]); + Py_DECREF(self->rows[1]); + Py_DECREF(self->rows[2]); + Py_DECREF(self->rows[3]); + + PyMem_DEL(self); +} + +#undef MethodDef +#define MethodDef(func) _MethodDef(func, Matrix) + +static char Matrix_inverse_doc[] = "() - returns inverse of matrix"; + +static PyObject *Matrix_inverse(PyObject *self, PyObject *args) +{ + float inverse[4][4]; + MatrixObject *mat = (MatrixObject *) self; + Mat4Invert(inverse, mat->mat); + return newMatrixObject(inverse); +} + +struct PyMethodDef Matrix_methods[] = { + MethodDef(inverse), + {NULL, NULL} +}; + +static PyObject *Matrix_getattr(MatrixObject *self, char *name) +{ + PyObject *list; + float val[3]; + + if (strcmp(name, "rot")==0) { + float mat3[3][3]; + + Mat3CpyMat4(mat3, self->mat); + Mat3ToEul(mat3, val); + + } else if (strcmp(name, "size")==0) { + Mat4ToSize(self->mat, val); + /* Oh man, this is BAD. */ + } else if (strcmp(name, "loc")==0) { + VECCOPY(val, (float *) (self->mat)[3]); + + } else { + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } + + list= PyList_New(3); + PyList_SetItem(list, 0, PyFloat_FromDouble(val[0])); + PyList_SetItem(list, 1, PyFloat_FromDouble(val[1])); + PyList_SetItem(list, 2, PyFloat_FromDouble(val[2])); + + return list; +} + +static int Matrix_setattr(MatrixObject *self, char *name, PyObject *v) { + return -1; +} + +static PyObject *Matrix_repr (MatrixObject *self) { + return BPY_tuple_repr((PyObject *) self, 4); +} + +static PyObject *Matrix_item(MatrixObject *self, int i) +{ + if (i < 0 || i >= 4) { + PyErr_SetString(PyExc_IndexError, "array index out of range"); + return NULL; + } + return BPY_incr_ret(self->rows[i]); +} + +static PySequenceMethods Matrix_SeqMethods = { + (inquiry) 0, /*sq_length*/ + (binaryfunc) 0, /*sq_concat*/ + (intargfunc) 0, /*sq_repeat*/ + (intargfunc) Matrix_item, /*sq_item*/ + (intintargfunc) 0, /*sq_slice*/ + (intobjargproc) 0, /*sq_ass_item*/ + (intintobjargproc) 0, /*sq_ass_slice*/ +}; + +PyTypeObject Matrix_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Matrix", /*tp_name*/ + sizeof(MatrixObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) Matrix_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) Matrix_getattr, /*tp_getattr*/ + (setattrfunc) Matrix_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) Matrix_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &Matrix_SeqMethods, /*tp_as_sequence*/ +}; + +PyObject *newMatrixObject(Matrix4Ptr mat) { + MatrixObject *self; + + self= PyObject_NEW(MatrixObject, &Matrix_Type); + self->mat= mat; + + BPY_TRY(self->rows[0]= newVectorObject(GETROWVECTOR(self->mat, 0), 4)); + BPY_TRY(self->rows[1]= newVectorObject(GETROWVECTOR(self->mat, 1), 4)); + BPY_TRY(self->rows[2]= newVectorObject(GETROWVECTOR(self->mat, 2), 4)); + BPY_TRY(self->rows[3]= newVectorObject(GETROWVECTOR(self->mat, 3), 4)); + + return (PyObject*) self; +} + +void init_py_matrix(void) { + Matrix_Type.ob_type = &PyType_Type; +} diff --git a/source/blender/bpython/intern/opy_nmesh.c b/source/blender/bpython/intern/opy_nmesh.c new file mode 100644 index 00000000000..48de7726dd8 --- /dev/null +++ b/source/blender/bpython/intern/opy_nmesh.c @@ -0,0 +1,1716 @@ +/* python.c MIXED MODEL + * + * june 99 + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "BPY_macros.h" +#include "b_interface.h" +#include "BPY_tools.h" +#include "BPY_main.h" + +#include "opy_datablock.h" +#include "opy_nmesh.h" + +#include "MEM_guardedalloc.h" +#include "BIF_editmesh.h" /* vertexnormals_mesh() */ +#include "BDR_editface.h" /* make_tfaces */ + +#include "BKE_mesh.h" +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_displist.h" +#include "BKE_screen.h" +#include "BKE_object.h" +#include "BPY_objtypes.h" +#include "BLI_blenlib.h" +#include "BIF_space.h" + +#include "opy_vector.h" + +#include "b_interface.h" +/* PROTOS */ + +static int convert_NMeshToMesh(Mesh *mesh, NMesh *nmesh); +static int unlink_existingMeshdata(Mesh *mesh); +void initNMesh(void); +PyObject *init_py_nmesh(void); +int BPY_check_sequence_consistency(PyObject *seq, PyTypeObject *against); + +/* TYPE OBJECTS */ + +PyTypeObject NMesh_Type; +PyTypeObject NMFace_Type; +PyTypeObject NMVert_Type; +PyTypeObject NMCol_Type; + +/* DEFINES */ + + +#define COL_R (b) +#define COL_G (g) +#define COL_B (r) +#define COL_A (a) + +#define COLOR_CONVERT(col,comp) (col##->COL_##) + +/* GLOBALS */ + +static PyObject *g_nmeshmodule = NULL; + +/*****************************/ +/* Mesh Color Object */ +/*****************************/ + +static void NMCol_dealloc(PyObject *self) { + PyMem_DEL(self); +} + +static NMCol *newcol (char r, char g, char b, char a) { + NMCol *mc= (NMCol *) PyObject_NEW(NMCol, &NMCol_Type); + + mc->r= r; + mc->g= g; + mc->b= b; + mc->a= a; + + return mc; +} + +static char NMeshmodule_Col_doc[]= +"([r, g, b, a]) - Get a new mesh color\n\ +\n\ +[r=255, g=255, b=255, a=255] Specify the color components"; + +static PyObject *NMeshmodule_Col(PyObject *self, PyObject *args) { + int r=255, g=255, b=255, a=255; + +/* +if(PyArg_ParseTuple(args, "fff|f", &fr, &fg, &fb, &fa)) + return (PyObject *) newcol(255.0 * fr, 255.0 * fg, 255.0 * fb, 255.0 * fa); + */ + if(PyArg_ParseTuple(args, "|iiii", &r, &g, &b, &a)) + return (PyObject *) newcol(r, g, b, a); + return NULL; +} + +static PyObject *NMCol_getattr(PyObject *self, char *name) { + NMCol *mc= (NMCol *) self; + + if (strcmp(name, "r")==0) return Py_BuildValue("i", mc->r); + else if (strcmp(name, "g")==0) return Py_BuildValue("i", mc->g); + else if (strcmp(name, "b")==0) return Py_BuildValue("i", mc->b); + else if (strcmp(name, "a")==0) return Py_BuildValue("i", mc->a); + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static int NMCol_setattr(PyObject *self, char *name, PyObject *v) { + NMCol *mc= (NMCol *) self; + int ival; + + if(!PyArg_Parse(v, "i", &ival)) return -1; + + CLAMP(ival, 0, 255); + + if (strcmp(name, "r")==0) mc->r= ival; + else if (strcmp(name, "g")==0) mc->g= ival; + else if (strcmp(name, "b")==0) mc->b= ival; + else if (strcmp(name, "a")==0) mc->a= ival; + else return -1; + + return 0; +} + +PyObject *NMCol_repr(NMCol *self) +{ + static char s[256]; + sprintf (s, "[NMCol - <%d, %d, %d, %d>]", self->r, self->g, self->b, self->a); + return Py_BuildValue("s", s); +} + +PyTypeObject NMCol_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NMCol", /*tp_name*/ + sizeof(NMCol), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) NMCol_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) NMCol_getattr, /*tp_getattr*/ + (setattrfunc) NMCol_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) NMCol_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + + +/*****************************/ +/* NMesh Python Object */ +/*****************************/ + + +static void NMFace_dealloc(PyObject *self) { + NMFace *mf= (NMFace *) self; + + Py_DECREF(mf->v); + Py_DECREF(mf->uv); + Py_DECREF(mf->col); + + PyMem_DEL(self); + +} + +static NMFace *newNMFace(PyObject *vertexlist) { + NMFace *mf= PyObject_NEW(NMFace, &NMFace_Type); + + mf->v= vertexlist; + mf->uv= PyList_New(0); + mf->tpage= NULL; + mf->mode = TF_DYNAMIC + TF_TEX; + mf->flag= TF_SELECT; + mf->transp= TF_SOLID; + mf->col= PyList_New(0); + + mf->smooth= 0; + mf->mat_nr= 0; + + return mf; +} + +static char NMeshmodule_Face_doc[]= +"(vertexlist = None) - Get a new face, and pass optional vertex list"; +static PyObject *NMeshmodule_Face(PyObject *self, PyObject *args) { + PyObject *vertlist = NULL; + BPY_TRY(PyArg_ParseTuple(args, "|O!", &PyList_Type, &vertlist)); + + if (!vertlist) { + vertlist = PyList_New(0); + } + return (PyObject *) newNMFace(vertlist); +} + +/* XXX this code will be used later... +static PyObject *Method_getmode(PyObject *self, PyObject *args) { + PyObject *dict, *list; + PyObject *constants, *values, *c; + int flag; + int i, n; + + list = PyList_New(0); + dict = PyObject_GetAttrString(g_nmeshmodule, "Const"); + + if (!dict) return 0; + + constants = PyDict_Keys(dict); + values = PyDict_Values(dict); + + n = PySequence_Length(constants); + for (i = 0; i < n; i++) + { + flag = PyInt_AsLong(PySequence_GetItem(values, i)); + if (flag & ((NMFace*) self)->mode) + { + c = PySequence_GetItem(constants, i); + PyList_Append(list, c) + } + } + return list; +} +*/ + +static char NMFace_append_doc[]= "(vert) - appends Vertex 'vert' to face vertex list"; + +static PyObject *NMFace_append(PyObject *self, PyObject *args) +{ + PyObject *vert; + NMFace *f= (NMFace *) self; + + BPY_TRY(PyArg_ParseTuple(args, "O!", &NMVert_Type, &vert)); + PyList_Append(f->v, vert); + RETURN_INC(Py_None); +} + + +#undef MethodDef +#define MethodDef(func) {#func, NMFace_##func, METH_VARARGS, NMFace_##func##_doc} + +static struct PyMethodDef NMFace_methods[] = { + MethodDef(append), + {NULL, NULL} +}; + +static PyObject *NMFace_getattr(PyObject *self, char *name) { + NMFace *mf= (NMFace *) self; + + if(strcmp(name, "v")==0) + return Py_BuildValue("O", mf->v); + else if (strcmp(name, "col")==0) + return Py_BuildValue("O", mf->col); + else if (strcmp(name, "mat")==0) // emulation XXX + return Py_BuildValue("i", mf->mat_nr); + else if (strcmp(name, "materialIndex")==0) + return Py_BuildValue("i", mf->mat_nr); + else if (strcmp(name, "smooth")==0) + return Py_BuildValue("i", mf->smooth); + else if (strcmp(name, "image")==0) { + if (mf->tpage) + return Py_BuildValue("O", (PyObject *) mf->tpage); + else + RETURN_INC(Py_None); + } + else if (strcmp(name, "mode")==0) + return Py_BuildValue("i", mf->mode); + else if (strcmp(name, "flag")==0) + return Py_BuildValue("i", mf->flag); + else if (strcmp(name, "transp")==0) + return Py_BuildValue("i", mf->transp); + else if (strcmp(name, "uv")==0) + return Py_BuildValue("O", mf->uv); + + return Py_FindMethod(NMFace_methods, (PyObject*)self, name); +/* + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +*/ +} + +static int NMFace_setattr(PyObject *self, char *name, PyObject *v) { + NMFace *mf= (NMFace *) self; + int ival; + PyObject *tmp; + + if (STREQ(name, "v")) { + if(PySequence_Check(v)) { + Py_DECREF(mf->v); + mf->v= BPY_incr_ret(v); + + return 0; + } + } else if (STREQ(name, "col")) { + if(PySequence_Check(v)) { + Py_DECREF(mf->col); + mf->col= BPY_incr_ret(v); + + return 0; + } + } else if (STREQ(name, "mat") || STREQ(name, "materialIndex")) { + PyArg_Parse(v, "i", &ival); + + mf->mat_nr= ival; + + return 0; + } else if (STREQ(name, "smooth")) { + PyArg_Parse(v, "i", &ival); + + mf->smooth= ival?1:0; + + return 0; + } else if (STREQ(name, "uv")) { + if(PySequence_Check(v)) { + Py_DECREF(mf->uv); + mf->uv= BPY_incr_ret(v); + return 0; + } + } else if (STREQ(name, "flag")) { + PyArg_Parse(v, "i", &ival); + mf->flag = ival; + return 0; + } else if (STREQ(name, "mode")) { + PyArg_Parse(v, "i", &ival); + mf->mode = ival; + return 0; + } else if (STREQ(name, "transp")) { + PyArg_Parse(v, "i", &ival); + mf->transp = ival; + return 0; + } else if (STREQ(name, "image")) { + PyArg_Parse(v, "O", &tmp); + if (tmp == Py_None) { + mf->tpage = 0; + return 0; + } + if (!DataBlock_isType((DataBlock *) tmp, ID_IM)) + { + PyErr_SetString(PyExc_TypeError, "expects Image Datablock type"); + return -1; + } + mf->tpage = (DataBlock *) tmp; + return 0; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + +static PyObject *NMFace_repr (PyObject *self) +{ + return PyString_FromString("[NMFace]"); +} + +static int NMFace_len(NMFace *self) +{ + return PySequence_Length(self->v); +} + +static PyObject *NMFace_item(NMFace *self, int i) +{ + return PySequence_GetItem(self->v, i); // new ref +} + +static PyObject *NMFace_slice(NMFace *self, int begin, int end) +{ + return PyList_GetSlice(self->v, begin, end); // new ref +} + +static PySequenceMethods NMFace_SeqMethods = { + (inquiry) NMFace_len, /* sq_length */ + (binaryfunc) 0, /* sq_concat */ + (intargfunc) 0, /* sq_repeat */ + (intargfunc) NMFace_item, /* sq_item */ + (intintargfunc) NMFace_slice, /* sq_slice */ + (intobjargproc) 0, /* sq_ass_item */ + (intintobjargproc) 0, /* sq_ass_slice */ +}; + + +PyTypeObject NMFace_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NMFace", /*tp_name*/ + sizeof(NMFace), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) NMFace_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) NMFace_getattr, /*tp_getattr*/ + (setattrfunc) NMFace_setattr,/*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) NMFace_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &NMFace_SeqMethods, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + + +static NMVert *newvert(float *co) { + NMVert *mv= PyObject_NEW(NMVert, &NMVert_Type); + + VECCOPY(mv->co, co); + mv->no[0]= mv->no[1]= mv->no[2]= 0.0; + mv->uvco[0]= mv->uvco[1]= mv->uvco[2]= 0.0; + + return mv; +} + +static char NMeshmodule_Vert_doc[]= +"([x, y, z]) - Get a new vertice\n\ +\n\ +[x, y, z] Specify new coordinates"; + +static PyObject *NMeshmodule_Vert(PyObject *self, PyObject *args) { + float co[3]= {0.0, 0.0, 0.0}; + + BPY_TRY(PyArg_ParseTuple(args, "|fff", &co[0], &co[1], &co[2])); + + return (PyObject *) newvert(co); +} + +static void NMVert_dealloc(PyObject *self) { + PyMem_DEL(self); +} + +static PyObject *NMVert_getattr(PyObject *self, char *name) { + NMVert *mv= (NMVert *) self; + + if (STREQ(name, "co") || STREQ(name, "loc")) return newVectorObject(mv->co, 3); + else if (STREQ(name, "no")) return newVectorObject(mv->no, 3); + else if (STREQ(name, "uvco")) return newVectorObject(mv->uvco, 3); + else if (STREQ(name, "index")) return PyInt_FromLong(mv->index); + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static int NMVert_setattr(PyObject *self, char *name, PyObject *v) { + NMVert *mv= (NMVert *) self; + int i; + + if (STREQ(name,"index")) { + PyArg_Parse(v, "i", &i); + mv->index= i; + return 0; + } else if (STREQ(name, "uvco")) { + if (!PyArg_ParseTuple(v, "ff|f", &(mv->uvco[0]), &(mv->uvco[1]), &(mv->uvco[2]))) { + PyErr_SetString(PyExc_AttributeError, "Vector tuple or triple expected"); + return -1; + } + return 0; +/* +PyErr_SetString(PyExc_AttributeError, "Use slice assignment: uvco[i]"); + return -1; + */ + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + + +static int NMVert_len(NMVert *self) { + return 3; +} + +static PyObject *NMVert_item(NMVert *self, int i) +{ + if (i < 0 || i >= 3) { + PyErr_SetString(PyExc_IndexError, "array index out of range"); + return NULL; + } + return Py_BuildValue("f", self->co[i]); +} + +static PyObject *NMVert_slice(NMVert *self, int begin, int end) +{ + PyObject *list; + int count; + + if (begin<0) begin= 0; + if (end>3) end= 3; + if (begin>end) begin= end; + + list= PyList_New(end-begin); + + for (count= begin; count<end; count++) + PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->co[count])); + + return list; +} + +static int NMVert_ass_item(NMVert *self, int i, PyObject *ob) +{ + if (i < 0 || i >= 3) { + PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); + return -1; + } + + if (!PyNumber_Check(ob)) { + PyErr_SetString(PyExc_IndexError, "NMVert member must be a number"); + return -1; + } + + self->co[i]= PyFloat_AsDouble(ob); +/* if(!PyArg_Parse(ob, "f", &)) return -1; */ + + return 0; +} + +/** I guess this hurts... + * sorry, couldn't resist (strubi) */ + +static int NMVert_ass_slice(NMVert *self, int begin, int end, PyObject *seq) +{ + int count; + + if (begin<0) begin= 0; + if (end>3) end= 3; + if (begin>end) begin= end; + + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation"); + return -1; + } + + if (PySequence_Length(seq)!=(end-begin)) { + PyErr_SetString(PyExc_TypeError, "size mismatch in slice assignment"); + return -1; + } + + for (count= begin; count<end; count++) { + PyObject *ob= PySequence_GetItem(seq, count); + if (!PyArg_Parse(ob, "f", &self->co[count])) { + Py_DECREF(ob); + return -1; + } + Py_DECREF(ob); + } + + return 0; +} + +static PySequenceMethods NMVert_SeqMethods = { + (inquiry) NMVert_len, /* sq_length */ + (binaryfunc) 0, /* sq_concat */ + (intargfunc) 0, /* sq_repeat */ + (intargfunc) NMVert_item, /* sq_item */ + (intintargfunc) NMVert_slice, /* sq_slice */ + (intobjargproc) NMVert_ass_item, /* sq_ass_item */ + (intintobjargproc) NMVert_ass_slice, /* sq_ass_slice */ +}; + +PyTypeObject NMVert_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NMVert", /*tp_name*/ + sizeof(NMVert), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) NMVert_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) NMVert_getattr, /*tp_getattr*/ + (setattrfunc) NMVert_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) 0, /*tp_repr*/ + 0, /*tp_as_number*/ + &NMVert_SeqMethods, /*tp_as_sequence*/ +}; + + +static void NMesh_dealloc(PyObject *self) { + NMesh *me= (NMesh *) self; + + Py_DECREF(me->name); + Py_DECREF(me->verts); + Py_DECREF(me->faces); + + PyMem_DEL(self); +} + + +static char NMesh_getSelectedFaces_doc[] = "(flag = None) - returns list of selected Faces\n\ +If flag = 1, return indices instead"; +static PyObject *NMesh_getSelectedFaces(PyObject *self, PyObject *args) +{ + NMesh *nm= (NMesh *) self; + Mesh *me = nm->mesh; + int flag = 0; + + TFace *tf; + int i; + PyObject *l= PyList_New(0); + + if (me == NULL) return NULL; + + tf = me->tface; + if (tf == 0) { + return l; + } + + if (!PyArg_ParseTuple(args, "|i", &flag)) + return NULL; + if (flag) { + for (i =0 ; i < me->totface; i++) { + if (tf[i].flag & TF_SELECT ) { + PyList_Append(l, PyInt_FromLong(i)); + } + } + } else { + for (i =0 ; i < me->totface; i++) { + if (tf[i].flag & TF_SELECT ) { + PyList_Append(l, PyList_GetItem(nm->faces, i)); + } + } + } + return l; +} + + +static char NMesh_getActiveFace_doc[] = "returns the index of the active face "; +static PyObject *NMesh_getActiveFace(PyObject *self, PyObject *args) +{ + if (((NMesh *)self)->sel_face < 0) + RETURN_INC(Py_None); + return Py_BuildValue("i", ((NMesh *)self)->sel_face); +} + +static char NMesh_hasVertexUV_doc[] = "(flag = None) - returns 1 if Mesh has per vertex UVs ('Sticky')\n\ +The optional argument sets the Sticky flag"; + +static PyObject *NMesh_hasVertexUV(PyObject *self, PyObject *args) +{ + NMesh *me= (NMesh *) self; + int flag; + + if (args) { + if (PyArg_ParseTuple(args, "i", &flag)) { + if(flag) me->flags |= NMESH_HASVERTUV; + else me->flags &= ~NMESH_HASVERTUV; + } + } + PyErr_Clear(); + if (me->flags & NMESH_HASVERTUV) + return BPY_incr_ret(Py_True); + else + return BPY_incr_ret(Py_False); +} + +static char NMesh_hasFaceUV_doc[] = "(flag = None) - returns 1 if Mesh has textured faces\n\ +The optional argument sets the textured faces flag"; + +static PyObject *NMesh_hasFaceUV(PyObject *self, PyObject *args) +{ + NMesh *me= (NMesh *) self; + int flag = -1; + + BPY_TRY(PyArg_ParseTuple(args, "|i", &flag)); + + switch (flag) { + case 0: + me->flags |= NMESH_HASFACEUV; + break; + case 1: + me->flags &= ~NMESH_HASFACEUV; + break; + default: + break; + } + + if (me->flags & NMESH_HASFACEUV) + return BPY_incr_ret(Py_True); + else + return BPY_incr_ret(Py_False); +} + + +static char NMesh_hasVertexColours_doc[] = "(flag = None) - returns 1 if Mesh has vertex colours.\n\ +The optional argument sets the vertex colour flag"; + +static PyObject *NMesh_hasVertexColours(PyObject *self, PyObject *args) +{ + NMesh *me= (NMesh *) self; + int flag = -1; + + BPY_TRY(PyArg_ParseTuple(args, "|i", &flag)); + + switch (flag) { + case 0: + me->flags &= ~NMESH_HASMCOL; + break; + case 1: + me->flags |= NMESH_HASMCOL; + break; + default: + break; + } + + if (me->flags & NMESH_HASMCOL) + return BPY_incr_ret(Py_True); + else + return BPY_incr_ret(Py_False); + +} + + +static char NMesh_update_doc[] = "updates the Mesh"; +static PyObject *NMesh_update(PyObject *self, PyObject *args) +{ + NMesh *nmesh= (NMesh *) self; + Mesh *mesh = nmesh->mesh; + + if (mesh) { + unlink_existingMeshdata(mesh); + convert_NMeshToMesh(mesh, nmesh); + mesh_update(mesh); + } else { + nmesh->mesh = Mesh_fromNMesh(nmesh); + } + + nmesh_updateMaterials(nmesh); +/** This is another ugly fix due to the weird material handling of blender. + * it makes sure that object material lists get updated (by their length) + * according to their data material lists, otherwise blender crashes. + * It just stupidly runs through all objects...BAD BAD BAD. + */ + test_object_materials((ID *)mesh); + + if (!during_script()) + allqueue(REDRAWVIEW3D, 0); + return PyInt_FromLong(1); + +} + + +Mesh *Mesh_fromNMesh(NMesh *nmesh) +{ + Mesh *mesh= NULL; + mesh = mesh_new(); // new empty mesh Bobject + if (!mesh) { + PyErr_SetString(PyExc_RuntimeError, "FATAL: could not create mesh object"); + return NULL; + } + + convert_NMeshToMesh(mesh, nmesh); + mesh_update(mesh); + return mesh; +} + +#ifdef EXPERIMENTAL + +static char NMesh_asMesh_doc[] = "returns free Mesh datablock object from NMesh"; +static PyObject *NMesh_asMesh(PyObject *self, PyObject *args) +{ + char *name= NULL; + Mesh *mesh= NULL; + NMesh *nmesh; + int recalc_normals= 1; + + nmesh = (NMesh *) self; + + BPY_TRY(PyArg_ParseTuple(args, "|si", &name, &recalc_normals)); + + if (!PySequence_Check(nmesh->verts)) + return BPY_err_ret_ob(PyExc_AttributeError, + "nmesh vertices are not a sequence"); + if (!PySequence_Check(nmesh->faces)) + return BPY_err_ret_ob(PyExc_AttributeError, + "nmesh faces are not a sequence"); + if (!PySequence_Check(nmesh->materials)) + return BPY_err_ret_ob(PyExc_AttributeError, + "nmesh materials are not a sequence"); + if (!BPY_check_sequence_consistency(nmesh->verts, &NMVert_Type)) + return BPY_err_ret_ob(PyExc_AttributeError, + "nmesh vertices must be NMVerts"); + if (!BPY_check_sequence_consistency(nmesh->faces, &NMFace_Type)) + return BPY_err_ret_ob(PyExc_AttributeError, + "nmesh faces must be NMFaces"); + + mesh = Mesh_fromNMesh(nmesh); + return DataBlock_fromData(mesh); +} + +#endif +static char NMesh_link_doc[] = "(object) - Links NMesh data with Object 'object'"; + +PyObject * NMesh_link(PyObject *self, PyObject *args) +{ + return DataBlock_link(self, args); +} + +#undef MethodDef +#define MethodDef(func) {#func, NMesh_##func, METH_VARARGS, NMesh_##func##_doc} + +static struct PyMethodDef NMesh_methods[] = { + MethodDef(hasVertexColours), + MethodDef(hasFaceUV), + MethodDef(hasVertexUV), + MethodDef(getActiveFace), + MethodDef(getSelectedFaces), + MethodDef(update), +#ifdef EXPERIMENTAL + MethodDef(asMesh), +#endif + {NULL, NULL} +}; + +static PyObject *NMesh_getattr(PyObject *self, char *name) { + NMesh *me= (NMesh *) self; + + if (STREQ(name, "name")) + return BPY_incr_ret(me->name); + + else if (STREQ(name, "block_type")) + return PyString_FromString("NMesh"); + + else if (STREQ(name, "materials")) + return BPY_incr_ret(me->materials); + + else if (STREQ(name, "verts")) + return BPY_incr_ret(me->verts); + + else if (STREQ(name, "users")) { + if (me->mesh) { + return PyInt_FromLong(me->mesh->id.us); + } else { // it's a free mesh: + return Py_BuildValue("i", 0); + } + } + + else if (STREQ(name, "faces")) + return BPY_incr_ret(me->faces); + + return Py_FindMethod(NMesh_methods, (PyObject*)self, name); + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static int NMesh_setattr(PyObject *self, char *name, PyObject *v) { + NMesh *me= (NMesh *) self; + + if (STREQ3(name, "verts", "faces", "materials")) { + if(PySequence_Check(v)) { + if(STREQ(name, "materials")) { + Py_DECREF(me->materials); + me->materials= BPY_incr_ret(v); + } else if (STREQ(name, "verts")) { + Py_DECREF(me->verts); + me->verts= BPY_incr_ret(v); + } else { + Py_DECREF(me->faces); + me->faces= BPY_incr_ret(v); + } + } else { + PyErr_SetString(PyExc_AttributeError, "expected a sequence"); + return -1; + } + } else { + PyErr_SetString(PyExc_AttributeError, name); + return -1; + } + + return 0; +} + +PyTypeObject NMesh_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NMesh", /*tp_name*/ + sizeof(NMesh), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) NMesh_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) NMesh_getattr, /*tp_getattr*/ + (setattrfunc) NMesh_setattr, /*tp_setattr*/ +}; + +static NMFace *nmface_from_data(NMesh *mesh, int vidxs[4], char mat_nr, char flag, TFace *tface, MCol *col) +{ + NMFace *newf= PyObject_NEW(NMFace, &NMFace_Type); + int i, len; + + if(vidxs[3]) len= 4; + else if(vidxs[2]) len= 3; + else len= 2; + + newf->v= PyList_New(len); + + for (i=0; i<len; i++) + PyList_SetItem(newf->v, i, BPY_incr_ret(PyList_GetItem(mesh->verts, vidxs[i]))); + + if (tface) { + newf->uv = PyList_New(len); // per-face UV coordinates + for (i = 0; i < len; i++) + { + PyList_SetItem(newf->uv, i, Py_BuildValue("(ff)", tface->uv[i][0], tface->uv[i][1])); + } + if (tface->tpage) + newf->tpage = (DataBlock *) DataBlock_fromData((void *) tface->tpage); /* pointer to image per face */ + else + newf->tpage = 0; + newf->mode = tface->mode; /* draw mode */ + newf->flag = tface->flag; /* select flag */ + newf->transp = tface->transp; /* transparency flag */ + col = (MCol *) (tface->col); + } else { + newf->tpage = 0; + newf->uv = PyList_New(0); + } + + newf->mat_nr= mat_nr; + newf->smooth= flag&ME_SMOOTH; + + if (col) { + newf->col= PyList_New(4); + for(i=0; i<4; i++, col++) + PyList_SetItem(newf->col, i, + (PyObject *) newcol(col->b, col->g, col->r, col->a)); + } else { + newf->col= PyList_New(0); + } + return newf; +} + +static NMFace *nmface_from_shortdata(NMesh *mesh, MFace *face, TFace *tface, MCol *col) +{ + int vidxs[4]; + vidxs[0]= face->v1; + vidxs[1]= face->v2; + vidxs[2]= face->v3; + vidxs[3]= face->v4; + + return nmface_from_data(mesh, vidxs, face->mat_nr, face->flag, tface, col); +} + +static NMFace *nmface_from_intdata(NMesh *mesh, MFaceInt *face, TFace *tface, MCol *col) +{ + int vidxs[4]; + vidxs[0]= face->v1; + vidxs[1]= face->v2; + vidxs[2]= face->v3; + vidxs[3]= face->v4; + + return nmface_from_data(mesh, vidxs, face->mat_nr, face->flag, tface, col); +} + +static NMVert *nmvert_from_data(NMesh *me, MVert *vert, MSticky *st, float *co, int idx) +{ + NMVert *mv= PyObject_NEW(NMVert, &NMVert_Type); + + VECCOPY (mv->co, co); + + mv->no[0]= vert->no[0]/32767.0; + mv->no[1]= vert->no[1]/32767.0; + mv->no[2]= vert->no[2]/32767.0; + + if (st) { + mv->uvco[0]= st->co[0]; + mv->uvco[1]= st->co[1]; + mv->uvco[2]= 0.0; + + } else mv->uvco[0]= mv->uvco[1]= mv->uvco[2]= 0.0; + + mv->index= idx; + + return mv; +} + +static int get_active_faceindex(Mesh *me) +{ + TFace *tf; + int i; + + if (me == NULL) return -1; + + tf = me->tface; + if (tf == 0) return -1; + + for (i =0 ; i < me->totface; i++) { + if (tf[i].flag & TF_ACTIVE ) { + return i; + } + } + return -1; +} + +static PyObject *newNMesh_internal(Mesh *oldmesh, DispListMesh *dlm, float *extverts) +{ + NMesh *me= PyObject_NEW(NMesh, &NMesh_Type); + me->flags= 0; + + if (!oldmesh) { + me->name= BPY_incr_ret(Py_None); + me->materials= PyList_New(0); + me->verts= PyList_New(0); + me->faces= PyList_New(0); + me->mesh= 0; + } else { + MVert *mverts; + MSticky *msticky; + MFaceInt *mfaceints; + MFace *mfaces; + TFace *tfaces; + MCol *mcols; + int i, totvert, totface; + + if (dlm) { + me->name= BPY_incr_ret(Py_None); + me->mesh= 0; + + msticky= NULL; + mfaces= NULL; + mverts= dlm->mvert; + mfaceints= dlm->mface; + tfaces= dlm->tface; + mcols= dlm->mcol; + + totvert= dlm->totvert; + totface= dlm->totface; + } else { + me->name= PyString_FromString(oldmesh->id.name+2); + me->mesh= oldmesh; + + mfaceints= NULL; + msticky= oldmesh->msticky; + mverts= oldmesh->mvert; + mfaces= oldmesh->mface; + tfaces= oldmesh->tface; + mcols= oldmesh->mcol; + + totvert= oldmesh->totvert; + totface= oldmesh->totface; + + me->sel_face= get_active_faceindex(oldmesh); + } + + if (msticky) me->flags |= NMESH_HASVERTUV; + if (tfaces) me->flags |= NMESH_HASFACEUV; + if (mcols) me->flags |= NMESH_HASMCOL; + + me->verts= PyList_New(totvert); + for (i=0; i<totvert; i++) { + MVert *oldmv= &mverts[i]; + MSticky *oldst= msticky?&msticky[i]:NULL; + float *vco= extverts?&extverts[i*3]:oldmv->co; + + PyList_SetItem(me->verts, i, (PyObject *) nmvert_from_data(me, oldmv, oldst, vco, i)); + } + + me->faces= PyList_New(totface); + for (i=0; i<totface; i++) { + TFace *oldtf= tfaces?&tfaces[i]:NULL; + MCol *oldmc= mcols?&mcols[i*4]:NULL; + + if (mfaceints) { + MFaceInt *oldmf= &mfaceints[i]; + PyList_SetItem(me->faces, i, (PyObject *) nmface_from_intdata(me, oldmf, oldtf, oldmc)); + } else { + MFace *oldmf= &mfaces[i]; + PyList_SetItem(me->faces, i, (PyObject *) nmface_from_shortdata(me, oldmf, oldtf, oldmc)); + } + } + me->materials = PyList_fromMaterialList(oldmesh->mat, oldmesh->totcol); + } + + return (PyObject *) me; +} + +PyObject *newNMesh(Mesh *oldmesh) +{ + return newNMesh_internal(oldmesh, NULL, NULL); +} + +static char NMeshmodule_New_doc[]= +"() - returns a new, empty NMesh mesh object\n"; + +static PyObject *NMeshmodule_New(PyObject *self, PyObject *args) +{ + return newNMesh(NULL); +} + +static char NMeshmodule_GetRaw_doc[]= +"([name]) - Get a raw mesh from Blender\n\ +\n\ +[name] Name of the mesh to be returned\n\ +\n\ +If name is not specified a new empty mesh is\n\ +returned, otherwise Blender returns an existing\n\ +mesh."; + +static PyObject *NMeshmodule_GetRaw(PyObject *self, PyObject *args) +{ + char *name=NULL; + Mesh *oldmesh=NULL; + + BPY_TRY(PyArg_ParseTuple(args, "|s", &name)); + + if(name) { + oldmesh = (Mesh *) getFromList(getMeshList(), name); + + if (!oldmesh) return BPY_incr_ret(Py_None); + } + return newNMesh(oldmesh); +} + +static char NMeshmodule_GetRawFromObject_doc[]= +"(name) - Get the raw mesh used by a Blender object\n" +"\n" +"(name) Name of the object to get the mesh from\n" +"\n" +"This returns the mesh as used by the object, which\n" +"means it contains all deformations and modifications."; + +static PyObject *NMeshmodule_GetRawFromObject(PyObject *self, PyObject *args) +{ + char *name; + Object *ob; + PyObject *nmesh; + + BPY_TRY(PyArg_ParseTuple(args, "s", &name)); + + ob= (Object*) getFromList(getObjectList(), name); + if (!ob) + return BPY_err_ret_ob(PyExc_AttributeError, name); + else if (ob->type!=OB_MESH) + return BPY_err_ret_ob(PyExc_AttributeError, "Object does not have Mesh data"); + else { + Mesh *me= (Mesh*) ob->data; + DispList *dl; + + if (mesh_uses_displist(me) && (dl= find_displist(&me->disp, DL_MESH))) + nmesh = newNMesh_internal(me, dl->mesh, NULL); + else if ((dl= find_displist(&ob->disp, DL_VERTS))) + nmesh = newNMesh_internal(me, NULL, dl->verts); + else + nmesh = newNMesh(me); + } + ((NMesh *) nmesh)->mesh = 0; // hack: to mark that (deformed) mesh is readonly, + // so the update function will not try to write it. + return nmesh; +} + +static void mvert_from_data(MVert *mv, MSticky *st, NMVert *from) +{ + VECCOPY (mv->co, from->co); + mv->no[0]= from->no[0]*32767.0; + mv->no[1]= from->no[1]*32767.0; + mv->no[2]= from->no[2]*32767.0; + + mv->flag= 0; + mv->mat_nr= 0; + + if (st) { + st->co[0]= from->uvco[0]; + st->co[1]= from->uvco[1]; + } +} + +/* TODO: this function is just a added hack. Don't look at the + * RGBA/BRGA confusion, it just works, but will never work with + * a restructured Blender */ + +static void assign_perFaceColors(TFace *tf, NMFace *from) +{ + MCol *col; + int i; + + col = (MCol *) (tf->col); + + if (col) { + int len= PySequence_Length(from->col); + + if(len>4) len= 4; + + for (i=0; i<len; i++, col++) { + NMCol *mc= (NMCol *) PySequence_GetItem(from->col, i); + if(!NMCol_Check(mc)) { + Py_DECREF(mc); + continue; + } + + col->r= mc->b; + col->b= mc->r; + col->g= mc->g; + col->a= mc->a; + + Py_DECREF(mc); + } + } +} + +static int assignFaceUV(TFace *tf, NMFace *nmface) +{ + PyObject *fuv, *tmp; + int i; + + fuv = nmface->uv; + if (PySequence_Length(fuv) == 0) + return 0; + /* fuv = [(u_1, v_1), ... (u_n, v_n)] */ + for (i = 0; i < PySequence_Length(fuv); i++) { + tmp = PyList_GetItem(fuv, i); /* stolen reference ! */ + if (!PyArg_ParseTuple(tmp, "ff", &(tf->uv[i][0]), &(tf->uv[i][1]))) + return 0; + } + if (nmface->tpage) /* image assigned ? */ + { + tf->tpage = nmface->tpage->data; + } + else + tf->tpage = 0; + + tf->mode = nmface->mode; /* copy mode */ + tf->flag = nmface->flag; /* copy flag */ + tf->transp = nmface->transp; /* copy transp flag */ + + /* assign vertex colours */ + assign_perFaceColors(tf, nmface); + return 1; +} + +static void mface_from_data(MFace *mf, TFace *tf, MCol *col, NMFace *from) +{ + NMVert *nmv; + + int i= PyList_Size(from->v); + if(i>=1) { + nmv= (NMVert *) PyList_GetItem(from->v, 0); + if (NMVert_Check(nmv) && nmv->index!=-1) mf->v1= nmv->index; + else mf->v1= 0; + } + if(i>=2) { + nmv= (NMVert *) PyList_GetItem(from->v, 1); + if (NMVert_Check(nmv) && nmv->index!=-1) mf->v2= nmv->index; + else mf->v2= 0; + } + if(i>=3) { + nmv= (NMVert *) PyList_GetItem(from->v, 2); + if (NMVert_Check(nmv) && nmv->index!=-1) mf->v3= nmv->index; + else mf->v3= 0; + } + if(i>=4) { + nmv= (NMVert *) PyList_GetItem(from->v, 3); + if (NMVert_Check(nmv) && nmv->index!=-1) mf->v4= nmv->index; + else mf->v4= 0; + } + + /* this function is evil: + + test_index_mface(mf, i); + + It rotates vertex indices, if there are illegal '0's (end marker) + in the vertex index list. + But it doesn't do that with vertex colours or texture coordinates... + */ + + if (tf) { + assignFaceUV(tf, from); + if (PyErr_Occurred()) + { + PyErr_Print(); + return; + } + + test_index_face(mf, tf, i); + } else { + test_index_mface(mf, i); + } + + mf->puno= 0; + mf->mat_nr= from->mat_nr; + mf->edcode= 0; + if (from->smooth) + mf->flag= ME_SMOOTH; + else + mf->flag= 0; + + if (col) { + int len= PySequence_Length(from->col); + + if(len>4) len= 4; + + for (i=0; i<len; i++, col++) { + NMCol *mc= (NMCol *) PySequence_GetItem(from->col, i); + if(!NMCol_Check(mc)) { + Py_DECREF(mc); + continue; + } + + col->b= mc->r; + col->g= mc->g; + col->r= mc->b; + col->a= mc->a; + + Py_DECREF(mc); + } + } +} + + +/* check for a valid UV sequence */ +static int check_validFaceUV(NMesh *nmesh) +{ + PyObject *faces; + NMFace *nmface; + int i, n; + + faces = nmesh->faces; + for (i = 0; i < PySequence_Length(faces); i++) { + nmface = (NMFace *) PyList_GetItem(faces, i); + n = + n = PySequence_Length(nmface->uv); + if (n != PySequence_Length(nmface->v)) + { + if (n > 0) + printf("Warning: different length of vertex and UV coordinate " + "list in face!\n"); + return 0; + } + } + return 1; +} + +static int unlink_existingMeshdata(Mesh *mesh) +{ + freedisplist(&mesh->disp); + unlink_mesh(mesh); + if(mesh->mvert) MEM_freeN(mesh->mvert); + if(mesh->mface) MEM_freeN(mesh->mface); + if(mesh->mcol) MEM_freeN(mesh->mcol); + if(mesh->msticky) MEM_freeN(mesh->msticky); + if(mesh->mat) MEM_freeN(mesh->mat); + if(mesh->tface) MEM_freeN(mesh->tface); + return 1; +} + +Material **nmesh_updateMaterials(NMesh *nmesh) +{ + Material **matlist; + Mesh *mesh = nmesh->mesh; + int len = PySequence_Length(nmesh->materials); + + if (!mesh) { + printf("FATAL INTERNAL ERROR: illegal call to updateMaterials()\n"); + return 0; + } + + if (len > 0) { + matlist = newMaterialList_fromPyList(nmesh->materials); + if (mesh->mat) + MEM_freeN(mesh->mat); + mesh->mat = matlist; + } else { + matlist = 0; + } + mesh->totcol = len; + return matlist; +} + +PyObject *NMesh_assignMaterials_toObject(NMesh *nmesh, Object *ob) +{ + DataBlock *block; + Material *ma; + int i; + short old_matmask; + + old_matmask = ob->colbits; // HACK: save previous colbits + ob->colbits = 0; // make assign_material work on mesh linked material + + for (i= 0; i < PySequence_Length(nmesh->materials); i++) { + block= (DataBlock *) PySequence_GetItem(nmesh->materials, i); + + if (DataBlock_isType(block, ID_MA)) { + ma = (Material *) block->data; + assign_material(ob, ma, i+1); // XXX don't use this function anymore + } else { + PyErr_SetString(PyExc_TypeError, + "Material type in attribute list 'materials' expected!"); + Py_DECREF(block); + return NULL; + } + + Py_DECREF(block); + } + ob->colbits = old_matmask; // HACK + + ob->actcol = 1; + RETURN_INC(Py_None); +} + +static int convert_NMeshToMesh(Mesh *mesh, NMesh *nmesh) +{ + MFace *newmf; + TFace *newtf; + MVert *newmv; + MSticky *newst; + MCol *newmc; + + int i, j; + + mesh->mvert= NULL; + mesh->mface= NULL; + mesh->mcol= NULL; + mesh->msticky= NULL; + mesh->tface = NULL; + mesh->mat= NULL; + + // material assignment moved to PutRaw + mesh->totvert= PySequence_Length(nmesh->verts); + if (mesh->totvert) { + if (nmesh->flags&NMESH_HASVERTUV) + mesh->msticky= MEM_callocN(sizeof(MSticky)*mesh->totvert, "msticky"); + + mesh->mvert= MEM_callocN(sizeof(MVert)*mesh->totvert, "mverts"); + } + + if (mesh->totvert) + mesh->totface= PySequence_Length(nmesh->faces); + else + mesh->totface= 0; + + + if (mesh->totface) { + +/* only create vertcol array if mesh has no texture faces */ + +/* TODO: get rid of double storage of vertex colours. In a mesh, + * vertex colors can be stored the following ways: + * - per (TFace*)->col + * - per (Mesh*)->mcol + * This is stupid, but will reside for the time being -- at least until + * a redesign of the internal Mesh structure */ + + if (!(nmesh->flags & NMESH_HASFACEUV) && (nmesh->flags&NMESH_HASMCOL)) + mesh->mcol= MEM_callocN(4*sizeof(MCol)*mesh->totface, "mcol"); + + mesh->mface= MEM_callocN(sizeof(MFace)*mesh->totface, "mfaces"); + } + + /* This stuff here is to tag all the vertices referenced + * by faces, then untag the vertices which are actually + * in the vert list. Any vertices untagged will be ignored + * by the mface_from_data function. It comes from my + * screwed up decision to not make faces only store the + * index. - Zr + */ + for (i=0; i<mesh->totface; i++) { + NMFace *mf= (NMFace *) PySequence_GetItem(nmesh->faces, i); + + j= PySequence_Length(mf->v); + while (j--) { + NMVert *mv= (NMVert *) PySequence_GetItem(mf->v, j); + if (NMVert_Check(mv)) mv->index= -1; + Py_DECREF(mv); + } + + Py_DECREF(mf); + } + + for (i=0; i<mesh->totvert; i++) { + NMVert *mv= (NMVert *) PySequence_GetItem(nmesh->verts, i); + mv->index= i; + Py_DECREF(mv); + } + + newmv= mesh->mvert; + newst= mesh->msticky; + for (i=0; i<mesh->totvert; i++) { + PyObject *mv= PySequence_GetItem(nmesh->verts, i); + mvert_from_data(newmv, newst, (NMVert *)mv); + Py_DECREF(mv); + + newmv++; + if (newst) newst++; + } + +/* assign per face texture UVs */ + + /* check face UV flag, then check whether there was one + * UV coordinate assigned, if yes, make tfaces */ + if ((nmesh->flags & NMESH_HASFACEUV) || (check_validFaceUV(nmesh))) { + make_tfaces(mesh); /* initialize TFaces */ + + newmc= mesh->mcol; + newmf= mesh->mface; + newtf= mesh->tface; + for (i=0; i<mesh->totface; i++) { + PyObject *mf= PySequence_GetItem(nmesh->faces, i); + mface_from_data(newmf, newtf, newmc, (NMFace *) mf); + Py_DECREF(mf); + + newtf++; + newmf++; + if (newmc) newmc++; + } + + nmesh->flags |= NMESH_HASFACEUV; + } else { + + newmc= mesh->mcol; + newmf= mesh->mface; + for (i=0; i<mesh->totface; i++) { + PyObject *mf= PySequence_GetItem(nmesh->faces, i); + mface_from_data(newmf, 0, newmc, (NMFace *) mf); + Py_DECREF(mf); + + newmf++; + if (newmc) newmc++; + } + } + return 1; +} + + + +static char NMeshmodule_PutRaw_doc[]= +"(mesh, [name, renormal]) - Return a raw mesh to Blender\n\ +\n\ +(mesh) The NMesh object to store\n\ +[name] The mesh to replace\n\ +[renormal=1] Flag to control vertex normal recalculation\n\ +\n\ +If the name of a mesh to replace is not given a new\n\ +object is created and returned."; + +static PyObject *NMeshmodule_PutRaw(PyObject *self, PyObject *args) +{ + char *name= NULL; + Mesh *mesh= NULL; + Object *ob= NULL; + NMesh *nmesh; + int recalc_normals= 1; + + BPY_TRY(PyArg_ParseTuple(args, "O!|si", &NMesh_Type, &nmesh, &name, &recalc_normals)); + + if (!PySequence_Check(nmesh->verts)) + return BPY_err_ret_ob(PyExc_AttributeError, "nmesh vertices are not a sequence"); + if (!PySequence_Check(nmesh->faces)) + return BPY_err_ret_ob(PyExc_AttributeError, "nmesh faces are not a sequence"); + if (!PySequence_Check(nmesh->materials)) + return BPY_err_ret_ob(PyExc_AttributeError, "nmesh materials are not a sequence"); + + if (!BPY_check_sequence_consistency(nmesh->verts, &NMVert_Type)) + return BPY_err_ret_ob(PyExc_AttributeError, "nmesh vertices must be NMVerts"); + if (!BPY_check_sequence_consistency(nmesh->faces, &NMFace_Type)) + return BPY_err_ret_ob(PyExc_AttributeError, "nmesh faces must be NMFaces"); + + if (name) + mesh= (Mesh *) getFromList(getMeshList(), name); + /* returns new mesh if not found */ + + if(!mesh || mesh->id.us==0) { + ob= add_object(OB_MESH); + if (!ob) { + PyErr_SetString(PyExc_RuntimeError, "Fatal: could not create mesh object"); + return 0; + } + if (mesh) + set_mesh(ob, mesh); + else + mesh= (Mesh *) ob->data; + } + if(name) new_id(getMeshList(), &mesh->id, name); + + unlink_existingMeshdata(mesh); + convert_NMeshToMesh(mesh, nmesh); + nmesh->mesh = mesh; + + if(recalc_normals) + vertexnormals_mesh(mesh, 0); + + mesh_update(mesh); + + if (!during_script()) + allqueue(REDRAWVIEW3D, 0); + + // OK...this requires some explanation: + // Materials can be assigned two ways: + // a) to the object data (in this case, the mesh) + // b) to the Object + // + // Case a) is wanted, if Mesh data should be shared among objects, + // as well as its materials (up to 16) + // Case b) is wanted, when Mesh data should be shared, but not the + // materials. For example, you want several checker boards sharing their + // mesh data, but having different colors. So you would assign material + // index 0 to all even, index 1 to all odd faces and bind the materials + // to the Object instead (MaterialButtons: [OB] button "link materials to object") + // + // This feature implies that pointers to materials can be stored in + // an object or a mesh. The number of total materials MUST be + // synchronized (ob->totcol <-> mesh->totcol). We avoid the dangerous + // direct access by calling blenderkernel/material.c:assign_material(). + + // The flags setting the material binding is found in ob->colbits, where + // each bit indicates the binding PER MATERIAL + + if (ob) { // we created a new object + NMesh_assignMaterials_toObject(nmesh, ob); + return DataBlock_fromData(ob); + } else { + RETURN_INC(Py_None); + } +} + +#undef MethodDef +#define MethodDef(func) {#func, NMeshmodule_##func, METH_VARARGS, NMeshmodule_##func##_doc} + +static struct PyMethodDef NMeshmodule_methods[] = { +// These should be: Mesh.Col, Mesh.Vert, Mesh.Face in fure +// -- for ownership reasons + MethodDef(Col), + MethodDef(Vert), + MethodDef(Face), + MethodDef(New), + MethodDef(GetRaw), + MethodDef(GetRawFromObject), + MethodDef(PutRaw), + {NULL, NULL} +}; +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(TF_##name)) + +/* set constants for face drawing mode -- see drawmesh.c */ + +static void init_NMeshConst(PyObject *d) +{ + insertConst(d, "BILLBOARD", PyInt_FromLong(TF_BILLBOARD2)); + //BPY_ADDCONST(d, BILLBOARD); + insertConst(d, "ALL", PyInt_FromLong(0xffff)); + BPY_ADDCONST(d, DYNAMIC); + BPY_ADDCONST(d, INVISIBLE); + insertConst(d, "HALO", PyInt_FromLong(TF_BILLBOARD)); + BPY_ADDCONST(d, LIGHT); + BPY_ADDCONST(d, OBCOL); + BPY_ADDCONST(d, SHADOW); + BPY_ADDCONST(d, SHAREDVERT); + BPY_ADDCONST(d, SHAREDCOL); + BPY_ADDCONST(d, TEX); + BPY_ADDCONST(d, TILES); + BPY_ADDCONST(d, TWOSIDE); +/* transparent modes */ + BPY_ADDCONST(d, SOLID); + BPY_ADDCONST(d, ADD); + BPY_ADDCONST(d, ALPHA); + BPY_ADDCONST(d, SUB); +/* TFACE flags */ + BPY_ADDCONST(d, SELECT); + BPY_ADDCONST(d, HIDE); + BPY_ADDCONST(d, ACTIVE); +} + +PyObject *init_py_nmesh(void) +{ + PyObject *d; + PyObject *mod= Py_InitModule(SUBMODULE(NMesh), NMeshmodule_methods); + PyObject *dict= PyModule_GetDict(mod); + + NMesh_Type.ob_type= &PyType_Type; + NMVert_Type.ob_type= &PyType_Type; + NMFace_Type.ob_type= &PyType_Type; + NMCol_Type.ob_type= &PyType_Type; + + d = ConstObject_New(); + PyDict_SetItemString(dict, "Const" , d); + init_NMeshConst(d); + + g_nmeshmodule = mod; + return mod; +} + +#ifdef SHAREDMODULE +void initNMesh(void) +{ + init_py_nmesh(); +} +#endif diff --git a/source/blender/bpython/intern/opy_nmesh.h b/source/blender/bpython/intern/opy_nmesh.h new file mode 100644 index 00000000000..778a726b26e --- /dev/null +++ b/source/blender/bpython/intern/opy_nmesh.h @@ -0,0 +1,93 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +/* opy_nmesh.c */ + +#include "DNA_mesh_types.h" + +#define NMesh_Check(v) ((v)->ob_type == &NMesh_Type) +#define NMFace_Check(v) ((v)->ob_type == &NMFace_Type) +#define NMVert_Check(v) ((v)->ob_type == &NMVert_Type) +#define NMCol_Check(v) ((v)->ob_type == &NMCol_Type) + +typedef struct _NMCol { + PyObject_HEAD + + unsigned char r, g, b, a; +} NMCol; + +struct PyBlock; + +typedef struct _NMFace { + PyObject_HEAD + + PyObject *v; + PyObject *uv; + PyObject *col; + short mode; + short flag; + unsigned char transp; + DataBlock *tpage; /* Image */ + char mat_nr, smooth; +} NMFace; + +typedef struct _NMesh { + PyObject_HEAD + Mesh *mesh; + PyObject *name; + PyObject *materials; + PyObject *verts; + PyObject *faces; + int sel_face; /* XXX remove */ + char flags; +#define NMESH_HASMCOL 1<<0 +#define NMESH_HASVERTUV 1<<1 +#define NMESH_HASFACEUV 1<<2 + +} NMesh; + +typedef struct _NMVert { + PyObject_VAR_HEAD + + float co[3]; + float no[3]; + float uvco[3]; + + int index; +} NMVert; + + +/* PROTOS */ + +PyObject *newNMesh(Mesh *oldmesh); +Mesh *Mesh_fromNMesh(NMesh *nmesh); +PyObject *NMesh_assignMaterials_toObject(NMesh *nmesh, Object *ob); +Material **nmesh_updateMaterials(NMesh *nmesh); diff --git a/source/blender/bpython/intern/opy_vector.c b/source/blender/bpython/intern/opy_vector.c new file mode 100644 index 00000000000..905c6aeed34 --- /dev/null +++ b/source/blender/bpython/intern/opy_vector.c @@ -0,0 +1,241 @@ +/* python.c MIXED MODEL + * + * june 99 + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Python.h" +#include "BPY_tools.h" +#include "BPY_macros.h" +#include "BPY_modules.h" +#include "opy_vector.h" + + + +/*****************************/ +/* Vector Python Object */ +/*****************************/ + +PyTypeObject Vector_Type; + + +#define VectorObject_Check(v) ((v)->ob_type == &Vector_Type) + + +static void Vector_dealloc(VectorObject *self) { + PyMem_DEL(self); +} + +static PyObject *Vector_getattr(VectorObject *self, char *name) { + if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0) + return PyFloat_FromDouble(self->vec[ name[0]-'x' ]); + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +static int Vector_setattr(VectorObject *self, char *name, PyObject *v) { + float val; + + BPY_TRY(PyArg_Parse(v, "f;Coordinates must be floats", &val)); + + if (self->size==3 && ELEM3(name[0], 'x', 'y', 'z') && name[1]==0) + self->vec[ name[0]-'x' ]= val; + else + return -1; + + return 0; +} + +/* Vectors utils */ + +/* XXX +int Vector_Parse(PyObject *vec) +{ + +} +*/ + +/* Vectors Sequence methods */ + +static int Vector_len(VectorObject *self) +{ + return self->size; +} + +static PyObject *Vector_item(VectorObject *self, int i) +{ + if (i < 0 || i >= self->size) { + PyErr_SetString(PyExc_IndexError, "array index out of range"); + return NULL; + } + return Py_BuildValue("f", self->vec[i]); +} + +static PyObject *Vector_slice(VectorObject *self, int begin, int end) +{ + PyObject *list; + int count; + + if (begin<0) begin= 0; + if (end>self->size) end= self->size; + if (begin>end) begin= end; + + list= PyList_New(end-begin); + + for (count= begin; count<end; count++) + PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->vec[count])); + + return list; +} + +static int Vector_ass_item(VectorObject *self, int i, PyObject *ob) +{ + if (i < 0 || i >= self->size) { + PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); + return -1; + } + + if (!PyNumber_Check(ob)) { + PyErr_SetString(PyExc_IndexError, "vector member must be a number"); + return -1; + } + + self->vec[i]= PyFloat_AsDouble(ob); +/* if(!PyArg_Parse(ob, "f", &)) return -1; */ + + return 0; +} + +static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) +{ + int count; + + if (begin<0) begin= 0; + if (end>self->size) end= self->size; + if (begin>end) begin= end; + + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, "illegal argument type for built-in operation"); + return -1; + } + + if (PySequence_Length(seq)!=(end-begin)) { + PyErr_SetString(PyExc_TypeError, "size mismatch in slice assignment"); + return -1; + } + + for (count= begin; count<end; count++) { + PyObject *ob= PySequence_GetItem(seq, count); + if (!PyArg_Parse(ob, "f", &self->vec[count])) { + Py_DECREF(ob); + return -1; + } + Py_DECREF(ob); + } + + return 0; +} + +PyObject *BPY_tuple_repr(PyObject *self, int size) +{ + PyObject *repr, *comma, *item; + int i; + + // note: a value must be built because the list is decrefed! + // otherwise we have nirvana pointers inside python.. + //PyObject *repr= Py_BuildValue("s", PyString_AsString(PyObject_Repr(list))); + repr = PyString_FromString("("); + if (!repr) return 0; + + item = PySequence_GetItem(self, 0); + PyString_ConcatAndDel(&repr, PyObject_Repr(item)); + Py_DECREF(item); + + comma = PyString_FromString(", "); + for (i = 1; i < size; i++) { + PyString_Concat(&repr, comma); + item = PySequence_GetItem(self, i); + PyString_ConcatAndDel(&repr, PyObject_Repr(item)); + Py_DECREF(item); + } + PyString_ConcatAndDel(&repr, PyString_FromString(")")); + Py_DECREF(comma); + return repr; + +} + + +static PyObject *Vector_repr (VectorObject *self) { + return BPY_tuple_repr((PyObject *) self, self->size); +} + +static PySequenceMethods Vector_SeqMethods = { + (inquiry) Vector_len, /* sq_length */ + (binaryfunc) 0, /* sq_concat */ + (intargfunc) 0, /* sq_repeat */ + (intargfunc) Vector_item, /* sq_item */ + (intintargfunc) Vector_slice, /* sq_slice */ + (intobjargproc) Vector_ass_item, /* sq_ass_item */ + (intintobjargproc) Vector_ass_slice, /* sq_ass_slice */ +}; + +PyTypeObject Vector_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Vector", /*tp_name*/ + sizeof(VectorObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) Vector_dealloc, /*tp_dealloc*/ + (printfunc) 0, /*tp_print*/ + (getattrfunc) Vector_getattr, /*tp_getattr*/ + (setattrfunc) Vector_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) Vector_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &Vector_SeqMethods, /*tp_as_sequence*/ +}; + +PyObject *newVectorObject(float *vec, int size) { + VectorObject *self; + + self= PyObject_NEW(VectorObject, &Vector_Type); + + self->vec= vec; + self->size= size; + + return (PyObject*) self; +} + +void init_py_vector(void) { + Vector_Type.ob_type = &PyType_Type; +} diff --git a/source/blender/bpython/intern/opy_vector.h b/source/blender/bpython/intern/opy_vector.h new file mode 100644 index 00000000000..cf7ca87fd6a --- /dev/null +++ b/source/blender/bpython/intern/opy_vector.h @@ -0,0 +1,63 @@ + + +/* Matrix and vector objects in Python */ + +/* $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +/*****************************/ +/* Matrix Python Object */ +/*****************************/ +/* temporar hack for typecasts */ + +typedef float (*Matrix4Ptr)[4]; +typedef struct { + PyObject_VAR_HEAD + float *vec; + int size; +} VectorObject; + +typedef struct { + PyObject_VAR_HEAD + PyObject *rows[4]; + Matrix4Ptr mat; +} MatrixObject; + + +/* PROTOS */ + +PyObject *newVectorObject(float *vec, int size); +PyObject *newMatrixObject(Matrix4Ptr mat); +void init_py_matrix(void); +void init_py_vector(void); + + diff --git a/source/blender/bpython/intern/opy_window.c b/source/blender/bpython/intern/opy_window.c new file mode 100644 index 00000000000..8aa976382a9 --- /dev/null +++ b/source/blender/bpython/intern/opy_window.c @@ -0,0 +1,194 @@ + +/* + * Python Blender Window module + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "Python.h" +#include "BPY_macros.h" +#include "b_interface.h" +#include "BPY_tools.h" +#include "BPY_main.h" +#include "BPY_window.h" + +#include "BSE_headerbuttons.h" + +#include "BIF_screen.h" // curarea +#include "BIF_space.h" // allqueue() +#include "BIF_drawtext.h" // pop_space_text +#include "mydevice.h" // for all the event constants + +#include "opy_datablock.h" +#include "opy_nmesh.h" + +#include "DNA_view3d_types.h" +#include "DNA_space_types.h" + + +/*********************************/ +/* helper routines */ + + +/** update current camera view */ + +void window_update_curCamera(Object *camera) +{ + copy_view3d_lock(REDRAW); +} + +char Windowmodule_QRedrawAll_doc[]= "() - Redraw all windows by queue event"; + +/* hack to flag that window redraw has happened inside slider callback: */ +int g_window_redrawn = 0; + +static PyObject *Windowmodule_QRedrawAll(PyObject *self, PyObject *args) +{ + int wintype = 0; + BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype)); + + allqueue(REDRAWALL, 0); + RETURN_INC(Py_None); +} +char Windowmodule_Redraw_doc[]= "() - Force a redraw of a specific Window Type; see Window.Const"; + +PyObject *Windowmodule_Redraw(PyObject *self, PyObject *args) +{ + ScrArea *tempsa, *sa; + SpaceText *st; + int wintype = SPACE_VIEW3D; + short redraw_all = 0; + + BPY_TRY(PyArg_ParseTuple(args, "|i", &wintype)); + + g_window_redrawn = 1; + + if (wintype < 0) + redraw_all = 1; + if (!during_script()) { + tempsa= curarea; + sa= getGlobal()->curscreen->areabase.first; + while(sa) { + + if (sa->spacetype== wintype || redraw_all) { + /* don't force-redraw Text window (Python GUI) when + redraw is called out of a slider update */ + if (sa->spacetype == SPACE_TEXT) { + st = sa->spacedata.first; + if (st->text->flags & TXT_FOLLOW) // follow cursor display + pop_space_text(st); + if (disable_force_draw) { + scrarea_queue_redraw(sa); + } + + + } else { + scrarea_do_windraw(sa); + if (sa->headwin) scrarea_do_headdraw(sa); + } + } + + sa= sa->next; + } + if(curarea!=tempsa) areawinset(tempsa->win); + + if (curarea->headwin) scrarea_do_headdraw(curarea); + screen_swapbuffers(); + } + + RETURN_INC(Py_None); +} + +char Windowmodule_RedrawAll_doc[]= "() - Redraw all windows"; +static PyObject *Windowmodule_RedrawAll(PyObject *self, PyObject *args) +{ + return Windowmodule_Redraw(self, Py_BuildValue("(i)", -1)); +} + +char Windowmodule_draw_progressbar_doc[]= "(done, text) - Draw a progressbar.\n\ +'done' is a float value <= 1.0, 'text' contains info about what is currently\n\ +being done"; + +static PyObject *Windowmodule_draw_progressbar(PyObject *self, PyObject *args) +{ + float done; + char *info = 0; + int retval; + + BPY_TRY(PyArg_ParseTuple(args, "fs", &done, &info)); + retval = progress_bar(done, info); + return Py_BuildValue("i", retval); +} + +#undef METHODDEF +#define METHODDEF(func) {#func, Windowmodule_##func, METH_VARARGS, Windowmodule_##func##_doc} + +static struct PyMethodDef Windowmodule_methods[] = { + METHODDEF(Redraw), + METHODDEF(QRedrawAll), + METHODDEF(RedrawAll), + METHODDEF(draw_progressbar), + + {NULL, NULL} +}; + + +#undef BPY_ADDCONST +#define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(SPACE_##name)) + +PyObject *INITMODULE(Window)(void) +{ + PyObject *d; + PyObject *mod= Py_InitModule(SUBMODULE(Window), Windowmodule_methods); + PyObject *dict= PyModule_GetDict(mod); + +/* from DNA_screen.types.h */ + d = ConstObject_New(); + PyDict_SetItemString(dict, "Types" , d); + + BPY_ADDCONST(d, VIEW3D); + BPY_ADDCONST(d, IPO); + BPY_ADDCONST(d, OOPS); + BPY_ADDCONST(d, BUTS); + BPY_ADDCONST(d, FILE); + BPY_ADDCONST(d, IMAGE); + BPY_ADDCONST(d, INFO); + BPY_ADDCONST(d, SEQ); + BPY_ADDCONST(d, IMASEL); + BPY_ADDCONST(d, SOUND); + BPY_ADDCONST(d, ACTION); + BPY_ADDCONST(d, TEXT); + BPY_ADDCONST(d, NLA); +/* BPY_ADDCONST(d, LOGIC); */ + + return mod; +} |