/* * * ***** 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. * * This is a new part of Blender. * * Contributor(s): Joseph Gilbert * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "logic.h" #include "gen_utils.h" #include #include //--------------- Python BPy_Property methods declarations:--------------------------------------------------- static PyObject *Property_getName (BPy_Property * self); static PyObject *Property_setName (BPy_Property * self, PyObject * args); static PyObject *Property_getData (BPy_Property * self); static PyObject *Property_setData (BPy_Property * self, PyObject * args); static PyObject *Property_getType (BPy_Property * self); //--------------- Python BPy_Property methods table:----------------------------------------------------------------- static PyMethodDef BPy_Property_methods[] = { {"getName", (PyCFunction) Property_getName, METH_NOARGS, "() - return Property name"}, {"setName", (PyCFunction)Property_setName, METH_VARARGS, "() - set the name of this Property"}, {"getData", (PyCFunction) Property_getData, METH_NOARGS, "() - return Property data"}, {"setData", (PyCFunction)Property_setData, METH_VARARGS, "() - set the data of this Property"}, {"getType", (PyCFunction) Property_getType, METH_NOARGS, "() - return Property type"}, {NULL, NULL, 0, NULL} }; //--------------- Python TypeProperty callback function prototypes---------------------------------------- static void Property_dealloc (BPy_Property * Property); static PyObject *Property_getAttr (BPy_Property * Property, char *name); static int Property_setAttr (BPy_Property * Property, char *name, PyObject * v); static PyObject *Property_repr (BPy_Property * Property); static int Property_compare (BPy_Property * a1, BPy_Property * a2); //--------------- Python TypeProperty structure definition------------------------------------------------------ PyTypeObject property_Type = { PyObject_HEAD_INIT (NULL) 0, /* ob_size */ "Blender Property", /* tp_name */ sizeof (BPy_Property), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor) Property_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc) Property_getAttr, /* tp_getattr */ (setattrfunc) Property_setAttr, /* tp_setattr */ (cmpfunc) Property_compare, /* tp_compare */ (reprfunc) Property_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_as_hash */ 0, 0, 0, 0, 0, 0, 0, /* tp_doc */ 0, 0, 0, 0, 0, 0, BPy_Property_methods, /* tp_methods */ 0, /* tp_members */ }; //--------------- Property module internal callbacks------------------------------------------------------------- //--------------- updatePyProperty------------------------------------------------------------------------------------- int updatePyProperty(BPy_Property *self) { if(!self->property){ return 0; //nothing to update - not linked }else{ BLI_strncpy(self->name, self->property->name, 32); self->type = self->property->type; if(self->property->type == PROP_BOOL){ if(*((int*)&self->property->poin)){ self->data = EXPP_incr_ret(Py_True); }else{ self->data = EXPP_incr_ret(Py_False); } }else if (self->property->type == PROP_INT){ self->data = PyInt_FromLong(self->property->data); }else if (self->property->type == PROP_FLOAT){ self->data = PyFloat_FromDouble(*((float*)&self->property->data)); }else if (self->property->type == PROP_TIME){ self->data = PyFloat_FromDouble(*((float*)&self->property->data)); }else if (self->property->type == PROP_STRING){ self->data = PyString_FromString(self->property->poin); } return 1; } return 0; } //--------------- updatePropertyData------------------------------------------------------------------------------------- int updateProperyData(BPy_Property *self) { if(!self->property){ //nothing to update - not linked return 0; }else{ BLI_strncpy(self->property->name, self->name, 32); self->property->type = self->type; if(PyInt_Check(self->data)){ *((int*)&self->property->data) = (int)PyInt_AsLong(self->data); }else if (PyFloat_Check(self->data)){ *((float *)&self->property->data) = (float)PyFloat_AsDouble(self->data); }else if (PyString_Check(self->data)){ BLI_strncpy(self->property->poin, PyString_AsString(self->data), MAX_PROPSTRING); } return 1; } return 0; } //--------------- checkValidData_ptr------------------------------------------------------------------------------------- int checkValidData_ptr(BPy_Property *self) { int length; //test pointer to see if data was removed (oops) length = MEM_allocN_len(self->property); if(length != sizeof(bProperty)){ //data was freed self->property = NULL; return 0; }else{ //it's ok as far as we can tell return 1; } } //---------------BPy_Property internal callbacks/methods--------------------------------------------- //--------------- dealloc--------------------------------------------------------------------------------------- static void Property_dealloc (BPy_Property * self) { PyMem_Free (self->name); PyObject_DEL (self); } //---------------getattr--------------------------------------------------------------------------------------- static PyObject * Property_getAttr (BPy_Property * self, char *name) { PyObject *attr = Py_None; checkValidData_ptr(self); if (strcmp (name, "name") == 0) attr = Property_getName (self); else if (strcmp (name, "data") == 0) attr = Property_getData (self); else if (strcmp (name, "type") == 0) attr = Property_getType (self); else if (strcmp (name, "__members__") == 0){ attr = Py_BuildValue ("[s,s,s]", "name", "data","type"); } if (!attr) return (EXPP_ReturnPyObjError (PyExc_MemoryError,"couldn't create PyObject")); if (attr != Py_None) return attr; return Py_FindMethod (BPy_Property_methods, (PyObject *) self, name); } //--------------- setattr--------------------------------------------------------------------------------------- static int Property_setAttr (BPy_Property * self, char *name, PyObject * value) { PyObject *valtuple; PyObject *error = NULL; checkValidData_ptr(self); valtuple = Py_BuildValue ("(O)", value); if (!valtuple) return EXPP_ReturnIntError (PyExc_MemoryError, "PropertySetAttr: couldn't create tuple"); if (strcmp (name, "name") == 0) error = Property_setName (self, valtuple); else if (strcmp(name, "data") == 0) error = Property_setData (self, valtuple); else{ Py_DECREF (valtuple); return (EXPP_ReturnIntError (PyExc_KeyError, "attribute not found")); } Py_DECREF (valtuple); if (error != Py_None) return -1; Py_DECREF (Py_None); return 0; } //--------------- repr--------------------------------------------------------------------------------------- static PyObject * Property_repr (BPy_Property * self) { checkValidData_ptr(self); if (self->property){ return PyString_FromFormat ("[Property \"%s\"]", self->property->name); }else{ return PyString_FromFormat ("[Property \"%s\"]", self->name); } } //--------------- compare--------------------------------------------------------------------------------------- //compares property.name and property.data static int Property_compare (BPy_Property * a, BPy_Property * b) { BPy_Property *py_propA, *py_propB; int retval = -1; checkValidData_ptr(a); checkValidData_ptr(b); //2 python objects if (!a->property && !b->property) { if(a->type != b->type) retval = -1; if(BLI_streq(a->name, b->name)){ retval = PyObject_Compare(a->data, b->data); }else retval = -1; }else if (a->property && b->property){ //2 real properties if(a->property->type != b->property->type) retval = -1; if(BLI_streq(a->property->name, b->property->name)){ if(a->property->type == PROP_BOOL || a->property->type == PROP_INT){ if(a->property->data == b->property->data) retval = 0; else retval = -1; }else if (a->property->type == PROP_FLOAT || a->property->type == PROP_TIME){ if(*((float*)&a->property->data) == *((float*)&b->property->data)) retval = 0; else retval = -1; }else if (a->property->type == PROP_STRING){ if(BLI_streq(a->property->poin, b->property->poin)) retval = 0; else retval = -1; } }else retval = -1; }else{ //1 real 1 python if(!a->property){ py_propA = a; py_propB = b; }else { py_propA = b; py_propB = a; } if(py_propB->property->type != py_propA->type) retval = -1; if(BLI_streq(py_propB->property->name, py_propA->name)){ if(py_propB->property->type == PROP_BOOL || py_propB->property->type == PROP_INT){ retval = PyObject_Compare(py_propA->data, PyInt_FromLong(py_propB->property->data)); }else if (py_propB->property->type == PROP_FLOAT || py_propB->property->type == PROP_TIME){ retval = PyObject_Compare(py_propA->data, PyFloat_FromDouble(*((float*)&py_propB->property->data))); }else if (py_propB->property->type == PROP_STRING){ retval = PyObject_Compare(py_propA->data, PyString_FromString(py_propB->property->poin)); } }else retval = -1; } return retval; } //--------------- Property visible functions-------------------------------------------------------------------- //--------------- Property_CreatePyObject-------------------------------------------------------------------- PyObject * Property_CreatePyObject (struct bProperty * Property) { BPy_Property *py_property; py_property = (BPy_Property *)PyObject_NEW (BPy_Property, &property_Type); //set the struct flag py_property->property = Property; //allocate space for python vars py_property->name= PyMem_Malloc (32); if(!updatePyProperty(py_property)) return (EXPP_ReturnPyObjError (PyExc_AttributeError , "Property struct empty")); return ((PyObject *) py_property); } //--------------- Property_CheckPyObject-------------------------------------------------------------------- int Property_CheckPyObject (PyObject * py_obj) { return (py_obj->ob_type == &property_Type); } //--------------- Property_FromPyObject-------------------------------------------------------------------- struct bProperty * Property_FromPyObject (PyObject * py_obj) { BPy_Property *py_property; py_property = (BPy_Property *) py_obj; if (!py_property->property) return NULL; else return (py_property->property); } //--------------- newPropertyObject()---------------------------------------------------------------------------- PyObject * newPropertyObject (char *name, PyObject *data, int type) { BPy_Property *py_property; py_property = (BPy_Property *)PyObject_NEW (BPy_Property, &property_Type); py_property->name= PyMem_Malloc (32); py_property->property = NULL; BLI_strncpy(py_property->name, name, 32); py_property->data = data; py_property->type = type; return (PyObject*)py_property; } //--------------- Python BPy_Property methods------------------------------------------------------------------ //--------------- BPy_Property.getName()-------------------------------------------------------------------------- static PyObject * Property_getName (BPy_Property * self) { PyObject *attr = NULL; if (!self->property) attr = PyString_FromString (self->name); else attr = PyString_FromString (self->property->name); if (attr) return attr; return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't get Property.name attribute")); } //--------------- BPy_Property.setName()-------------------------------------------------------------------------- static PyObject * Property_setName (BPy_Property * self, PyObject * args) { char *name; if (!PyArg_ParseTuple (args, "s", &name)) return (EXPP_ReturnPyObjError (PyExc_AttributeError, "expected string argument")); if (!self->property){ BLI_strncpy(self->name, name, 32); }else{ BLI_strncpy(self->property->name, name, 32); updatePyProperty(self); } return EXPP_incr_ret (Py_None); } //--------------- BPy_Property.getData()-------------------------------------------------------------------------- static PyObject * Property_getData (BPy_Property * self) { PyObject *attr = NULL; if (!self->property) { attr = EXPP_incr_ret(self->data); }else{ if(self->property->type == PROP_BOOL){ if(*((int*)&self->property->poin)) attr = EXPP_incr_ret(Py_True); else attr = EXPP_incr_ret(Py_False); }else if (self->property->type == PROP_INT){ attr = PyInt_FromLong(self->property->data); }else if (self->property->type == PROP_FLOAT || self->property->type == PROP_TIME){ attr = PyFloat_FromDouble(*((float*)&self->property->data)); }else if (self->property->type == PROP_STRING){ attr = PyString_FromString(self->property->poin); } } if (attr) return attr; return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't get Property.name attribute")); } //--------------- BPy_Property.setData()-------------------------------------------------------------------------- static PyObject * Property_setData (BPy_Property * self, PyObject * args) { PyObject *data; char *type_str = NULL; int type = -1; short *p_type = NULL; if (!PyArg_ParseTuple (args, "O|s", &data, &type_str)) return (EXPP_ReturnPyObjError (PyExc_AttributeError, "expected object and optional string argument")); if(!PyInt_Check(data) && !PyFloat_Check(data) && !PyString_Check(data)) return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "float, int, or string expected as data")); //parse property name if(type_str){ if(BLI_streq(type_str, "BOOL")) type = PROP_BOOL; else if (BLI_streq(type_str, "INT")) type = PROP_INT; else if (BLI_streq(type_str, "FLOAT")) type = PROP_FLOAT; else if (BLI_streq(type_str, "TIME")) type = PROP_TIME; else if (BLI_streq(type_str, "STRING")) type = PROP_STRING; else return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "BOOL, INT, FLOAT, TIME or STRING expected")); } //get pointer to type if(self->property) p_type = &self->property->type; else p_type = &self->type; //set the type if(PyInt_Check(data)){ if(type == -1 || type == PROP_INT) *p_type = PROP_INT; else *p_type = PROP_BOOL; }else if(PyFloat_Check(data)){ if(type == -1 || type == PROP_FLOAT) *p_type = PROP_FLOAT; else *p_type = PROP_TIME; }else if(PyString_Check(data)){ if(type == -1 || type == PROP_STRING) *p_type = PROP_STRING; }else{ return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "cant set unknown data type")); } //set the data if(self->property){ if(PyInt_Check(data)){ *((int*)&self->property->data) = (int)PyInt_AsLong(data); }else if (PyFloat_Check(data)){ *((float *)&self->property->data) = (float)PyFloat_AsDouble(data); }else if (PyString_Check(data)){ BLI_strncpy(self->property->poin, PyString_AsString(data), MAX_PROPSTRING); } updatePyProperty(self); }else{ self->data = data; } return EXPP_incr_ret (Py_None); } //--------------- BPy_Property.getType()-------------------------------------------------------------------------- static PyObject * Property_getType (BPy_Property * self) { PyObject *attr = Py_None; int type; if(self->property) type = self->property->type; else type = self->type; if(type == PROP_BOOL) attr = Py_BuildValue("s", "BOOL"); else if (type == PROP_INT) attr = Py_BuildValue("s", "INT"); else if (type == PROP_FLOAT) attr = Py_BuildValue("s", "FLOAT"); else if (type == PROP_STRING) attr = Py_BuildValue("s", "STRING"); else if (type == PROP_TIME) attr = Py_BuildValue("s", "TIME"); return attr; }