| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 15:29:57 +00:00
										 |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #ifndef NO_EXP_PYTHON_EMBEDDING
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus cpp | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * C++ library routines for Crawl 3.2 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Derived from work by | 
					
						
							|  |  |  |  * David Redish | 
					
						
							|  |  |  |  * graduate student | 
					
						
							|  |  |  |  * Computer Science Department  | 
					
						
							|  |  |  |  * Carnegie Mellon University (CMU) | 
					
						
							|  |  |  |  * Center for the Neural Basis of Cognition (CNBC)  | 
					
						
							|  |  |  |  * http://www.python.org/doc/PyCPP.html
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2005-03-25 10:33:39 +00:00
										 |  |  | #include <MT_assert.h>
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "stdlib.h"
 | 
					
						
							|  |  |  | #include "PyObjectPlus.h"
 | 
					
						
							|  |  |  | #include "STR_String.h"
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Type		-- Every class, even the abstract one should have a Type | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PyObjectPlus::Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,				/*ob_size*/ | 
					
						
							|  |  |  | 	"PyObjectPlus",			/*tp_name*/ | 
					
						
							|  |  |  | 	sizeof(PyObjectPlus),		/*tp_basicsize*/ | 
					
						
							|  |  |  | 	0,				/*tp_itemsize*/ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	PyDestructor,	  		/*tp_dealloc*/ | 
					
						
							|  |  |  | 	0,			 	/*tp_print*/ | 
					
						
							|  |  |  | 	__getattr, 			/*tp_getattr*/ | 
					
						
							|  |  |  | 	__setattr, 			/*tp_setattr*/ | 
					
						
							|  |  |  | 	0,			        /*tp_compare*/ | 
					
						
							|  |  |  | 	__repr,			        /*tp_repr*/ | 
					
						
							|  |  |  | 	0,			        /*tp_as_number*/ | 
					
						
							|  |  |  | 	0,		 	        /*tp_as_sequence*/ | 
					
						
							|  |  |  | 	0,			        /*tp_as_mapping*/ | 
					
						
							|  |  |  | 	0,			        /*tp_hash*/ | 
					
						
							|  |  |  | 	0,				/*tp_call */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-20 09:13:06 +00:00
										 |  |  | PyObjectPlus::~PyObjectPlus() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-01-30 20:33:59 +00:00
										 |  |  | 	if (ob_refcnt) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		_Py_ForgetReference(this); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-12-20 09:13:06 +00:00
										 |  |  | //	assert(ob_refcnt==0);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | PyObjectPlus::PyObjectPlus(PyTypeObject *T) 				// constructor
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-03-25 10:33:39 +00:00
										 |  |  | 	MT_assert(T != NULL); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	this->ob_type = T;  | 
					
						
							|  |  |  | 	_Py_NewReference(this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Methods 	-- Every class, even the abstract one should have a Methods | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyMethodDef PyObjectPlus::Methods[] = { | 
					
						
							| 
									
										
										
										
											2009-02-19 07:01:49 +00:00
										 |  |  |   {"isA",		 (PyCFunction) sPy_isA,			METH_O}, | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   {NULL, NULL}		/* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Parents		-- Every class, even the abstract one should have parents | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus attributes	-- attributes | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | PyObject *PyObjectPlus::_getattr(const char *attr) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | 	if (!strcmp(attr, "__doc__") && GetType()->tp_doc) | 
					
						
							| 
									
										
										
										
											2004-05-21 09:18:42 +00:00
										 |  |  | 		return PyString_FromString(GetType()->tp_doc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   //if (streq(attr, "type"))
 | 
					
						
							|  |  |  |   //  return Py_BuildValue("s", (*(GetParents()))->tp_name);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  |   return Py_FindMethod(Methods, this, attr); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | int PyObjectPlus::_delattr(const char *attr) | 
					
						
							| 
									
										
										
										
											2004-11-22 10:19:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-09-03 06:43:07 +00:00
										 |  |  | 	PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); | 
					
						
							| 
									
										
										
										
											2004-11-22 10:19:19 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | int PyObjectPlus::_setattr(const char *attr, PyObject *value) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	//return PyObject::_setattr(attr,value);
 | 
					
						
							|  |  |  | 	//cerr << "Unknown attribute" << endl;
 | 
					
						
							| 
									
										
										
										
											2008-09-03 06:43:07 +00:00
										 |  |  | 	PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	const PyAttributeDef *attrdef; | 
					
						
							|  |  |  | 	for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | 		if (!strcmp(attr, attrdef->m_name)) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// fake attribute, ignore
 | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; | 
					
						
							|  |  |  | 			if (attrdef->m_length > 1) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				PyObject* resultlist = PyList_New(attrdef->m_length); | 
					
						
							|  |  |  | 				for (int i=0; i<attrdef->m_length; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					switch (attrdef->m_type) { | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							bool *val = reinterpret_cast<bool*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(bool); | 
					
						
							|  |  |  | 							PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							short int *val = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(short int); | 
					
						
							|  |  |  | 							PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 						// enum are like int, just make sure the field size is the same
 | 
					
						
							|  |  |  | 						if (sizeof(int) != attrdef->m_size) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							Py_DECREF(resultlist); | 
					
						
							|  |  |  | 							return NULL; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						// walkthrough
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							int *val = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(int); | 
					
						
							|  |  |  | 							PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							float *val = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(float); | 
					
						
							|  |  |  | 							PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val)); | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					default: | 
					
						
							|  |  |  | 						// no support for array of complex data
 | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						Py_DECREF(resultlist); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						return NULL; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resultlist; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				switch (attrdef->m_type) { | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						bool *val = reinterpret_cast<bool*>(ptr); | 
					
						
							|  |  |  | 						return PyInt_FromLong(*val); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						short int *val = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 						return PyInt_FromLong(*val); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 					// enum are like int, just make sure the field size is the same
 | 
					
						
							|  |  |  | 					if (sizeof(int) != attrdef->m_size) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						return NULL; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					// walkthrough
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						int *val = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 						return PyInt_FromLong(*val); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						float *val = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 						return PyFloat_FromDouble(*val); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						STR_String *val = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 						return PyString_FromString(*val); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	const PyAttributeDef *attrdef; | 
					
						
							|  |  |  | 	void *undoBuffer = NULL; | 
					
						
							|  |  |  | 	void *sourceBuffer = NULL; | 
					
						
							|  |  |  | 	size_t bufferSize = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-02-19 13:42:07 +00:00
										 |  |  | 		if (!strcmp(attr, attrdef->m_name)) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (attrdef->m_access == KX_PYATTRIBUTE_RO || | 
					
						
							|  |  |  | 				attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_AttributeError, "property is read-only"); | 
					
						
							|  |  |  | 				return 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; | 
					
						
							|  |  |  | 			if (attrdef->m_length > 1) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (!PySequence_Check(value))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, "expected a sequence"); | 
					
						
							|  |  |  | 					return 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (PySequence_Size(value) != attrdef->m_length) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence"); | 
					
						
							|  |  |  | 					return 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				switch (attrdef->m_type)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 					bufferSize = sizeof(bool); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 					bufferSize = sizeof(short int); | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 					bufferSize = sizeof(int); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 					bufferSize = sizeof(float); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					// should not happen
 | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org"); | 
					
						
							|  |  |  | 					return 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// let's implement a smart undo method
 | 
					
						
							|  |  |  | 				bufferSize *= attrdef->m_length; | 
					
						
							|  |  |  | 				undoBuffer = malloc(bufferSize); | 
					
						
							|  |  |  | 				sourceBuffer = ptr; | 
					
						
							|  |  |  | 				if (undoBuffer) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					memcpy(undoBuffer, sourceBuffer, bufferSize); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for (int i=0; i<attrdef->m_length; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyObject *item = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							|  |  |  | 					// we can decrement the reference immediately, the reference count
 | 
					
						
							|  |  |  | 					// is at least 1 because the item is part of an array
 | 
					
						
							|  |  |  | 					Py_DECREF(item); | 
					
						
							|  |  |  | 					switch (attrdef->m_type)  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							bool *var = reinterpret_cast<bool*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(bool); | 
					
						
							|  |  |  | 							if (PyInt_Check(item))  | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								*var = (PyInt_AsLong(item) != 0); | 
					
						
							|  |  |  | 							}  | 
					
						
							|  |  |  | 							else if (PyBool_Check(item)) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								*var = (item == Py_True); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); | 
					
						
							|  |  |  | 								goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							short int *var = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(short int); | 
					
						
							|  |  |  | 							if (PyInt_Check(item))  | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								long val = PyInt_AsLong(item); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 								if (attrdef->m_clamp) | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 										val = attrdef->m_imin; | 
					
						
							|  |  |  | 									else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 										val = attrdef->m_imax; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 								{ | 
					
						
							|  |  |  | 									PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							|  |  |  | 									goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								*var = (short int)val; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 								goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 						// enum are equivalent to int, just make sure that the field size matches:
 | 
					
						
							|  |  |  | 						if (sizeof(int) != attrdef->m_size) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); | 
					
						
							|  |  |  | 							goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						// walkthrough
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							int *var = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(int); | 
					
						
							|  |  |  | 							if (PyInt_Check(item))  | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								long val = PyInt_AsLong(item); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 								if (attrdef->m_clamp) | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 										val = attrdef->m_imin; | 
					
						
							|  |  |  | 									else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 										val = attrdef->m_imax; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 								{ | 
					
						
							|  |  |  | 									PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							|  |  |  | 									goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								*var = (int)val; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 								goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							float *var = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 							ptr += sizeof(float); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							double val = PyFloat_AsDouble(item); | 
					
						
							|  |  |  | 							if (val == -1.0 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 								PyErr_SetString(PyExc_TypeError, "expected a float"); | 
					
						
							|  |  |  | 								goto UNDO_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							else if (attrdef->m_clamp)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 								if (val < attrdef->m_fmin) | 
					
						
							|  |  |  | 									val = attrdef->m_fmin; | 
					
						
							|  |  |  | 								else if (val > attrdef->m_fmax) | 
					
						
							|  |  |  | 									val = attrdef->m_fmax; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else if (val < attrdef->m_fmin || val > attrdef->m_fmax) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 								goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							*var = (float)val; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					default: | 
					
						
							|  |  |  | 						// should not happen
 | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org"); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// no error, call check function if any
 | 
					
						
							|  |  |  | 				if (attrdef->m_function != NULL) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					if ((*attrdef->m_function)(self, attrdef) != 0) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							|  |  |  | 						// post check returned an error, restore values
 | 
					
						
							|  |  |  | 					UNDO_AND_ERROR: | 
					
						
							|  |  |  | 						if (undoBuffer) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							memcpy(sourceBuffer, undoBuffer, bufferSize); | 
					
						
							|  |  |  | 							free(undoBuffer); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (undoBuffer) | 
					
						
							|  |  |  | 					free(undoBuffer); | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else	// simple attribute value
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (attrdef->m_function != NULL) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					// post check function is provided, prepare undo buffer
 | 
					
						
							|  |  |  | 					sourceBuffer = ptr; | 
					
						
							|  |  |  | 					switch (attrdef->m_type)  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 						bufferSize = sizeof(bool); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 						bufferSize = sizeof(short); | 
					
						
							|  |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 						bufferSize = sizeof(int); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 						bufferSize = sizeof(float); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 						sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr(); | 
					
						
							|  |  |  | 						if (sourceBuffer) | 
					
						
							|  |  |  | 							bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					default: | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); | 
					
						
							|  |  |  | 						return 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (bufferSize) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						undoBuffer = malloc(bufferSize); | 
					
						
							|  |  |  | 						if (undoBuffer) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							memcpy(undoBuffer, sourceBuffer, bufferSize); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 				switch (attrdef->m_type)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						bool *var = reinterpret_cast<bool*>(ptr); | 
					
						
							|  |  |  | 						if (PyInt_Check(value))  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							*var = (PyInt_AsLong(value) != 0); | 
					
						
							|  |  |  | 						}  | 
					
						
							|  |  |  | 						else if (PyBool_Check(value)) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							*var = (value == Py_True); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); | 
					
						
							|  |  |  | 							goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						short int *var = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 						if (PyInt_Check(value))  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							long val = PyInt_AsLong(value); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							if (attrdef->m_clamp) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 									val = attrdef->m_imin; | 
					
						
							|  |  |  | 								else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 									val = attrdef->m_imax; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							|  |  |  | 								goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							*var = (short int)val; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 							goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 					// enum are equivalent to int, just make sure that the field size matches:
 | 
					
						
							|  |  |  | 					if (sizeof(int) != attrdef->m_size) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					// walkthrough
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						int *var = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 						if (PyInt_Check(value))  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							long val = PyInt_AsLong(value); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							if (attrdef->m_clamp) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 									val = attrdef->m_imin; | 
					
						
							|  |  |  | 								else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 									val = attrdef->m_imax; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							|  |  |  | 								goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							*var = (int)val; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 							goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						float *var = reinterpret_cast<float*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						double val = PyFloat_AsDouble(value); | 
					
						
							|  |  |  | 						if (val == -1.0 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							PyErr_SetString(PyExc_TypeError, "expected a float"); | 
					
						
							|  |  |  | 							goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						else if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							if (val < attrdef->m_fmin) | 
					
						
							|  |  |  | 								val = attrdef->m_fmin; | 
					
						
							|  |  |  | 							else if (val > attrdef->m_fmax) | 
					
						
							|  |  |  | 								val = attrdef->m_fmax; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else if (val < attrdef->m_fmin || val > attrdef->m_fmax) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						*var = (float)val; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						STR_String *var = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 						if (PyString_Check(value))  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							char *val = PyString_AsString(value); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							if (attrdef->m_clamp) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								if (strlen(val) < attrdef->m_imin) | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									// can't increase the length of the string
 | 
					
						
							|  |  |  | 									PyErr_SetString(PyExc_ValueError, "string length too short"); | 
					
						
							|  |  |  | 									goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								else if (strlen(val) > attrdef->m_imax) | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									// trim the string
 | 
					
						
							|  |  |  | 									char c = val[attrdef->m_imax]; | 
					
						
							|  |  |  | 									val[attrdef->m_imax] = 0; | 
					
						
							|  |  |  | 									*var = val; | 
					
						
							|  |  |  | 									val[attrdef->m_imax] = c; | 
					
						
							|  |  |  | 									break; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_SetString(PyExc_ValueError, "string length out of range"); | 
					
						
							|  |  |  | 								goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							*var = val; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_TypeError, "expected a string"); | 
					
						
							|  |  |  | 							goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					// should not happen
 | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// check if post processing is needed
 | 
					
						
							|  |  |  | 			if (attrdef->m_function != NULL) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 				if ((*attrdef->m_function)(self, attrdef) != 0) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					// restore value
 | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 				RESTORE_AND_ERROR: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					if (undoBuffer) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							// special case for STR_String: restore the string
 | 
					
						
							|  |  |  | 							STR_String *var = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 							*var = reinterpret_cast<char*>(undoBuffer); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							// other field type have direct values
 | 
					
						
							|  |  |  | 							memcpy(ptr, undoBuffer, bufferSize); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				FREE_AND_ERROR: | 
					
						
							|  |  |  | 					if (undoBuffer) | 
					
						
							|  |  |  | 						free(undoBuffer); | 
					
						
							|  |  |  | 					return 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (undoBuffer) | 
					
						
							|  |  |  | 				free(undoBuffer); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return -1;			 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus repr		-- representations | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyObject *PyObjectPlus::_repr(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-08-14 03:23:36 +00:00
										 |  |  | 	PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");   | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus isA		-- the isA functions | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | bool PyObjectPlus::isA(PyTypeObject *T)		// if called with a Type, use "typename"
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return isA(T->tp_name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool PyObjectPlus::isA(const char *mytypename)		// check typename of each parent
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   PyParentObject  P; | 
					
						
							|  |  |  |   PyParentObject *Ps = GetParents(); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   for (P = Ps[i=0]; P != NULL; P = Ps[i++]) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2009-02-19 07:01:49 +00:00
										 |  |  |       if (strcmp(P->tp_name, mytypename)==0) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 		  return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 07:01:49 +00:00
										 |  |  | PyObject *PyObjectPlus::Py_isA(PyObject *value)		// Python wrapper for isA
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-19 07:01:49 +00:00
										 |  |  |   if (!PyString_Check(value)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_TypeError, "expected a string"); | 
					
						
							| 
									
										
										
										
											2008-08-14 03:23:36 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2009-02-19 07:01:49 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   if(isA(PyString_AsString(value))) | 
					
						
							| 
									
										
										
										
											2008-08-14 03:23:36 +00:00
										 |  |  |     Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2008-08-14 03:23:36 +00:00
										 |  |  |     Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif //NO_EXP_PYTHON_EMBEDDING
 | 
					
						
							|  |  |  | 
 |