| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | #include "MT_Vector3.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Type		-- Every class, even the abstract one should have a Type | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | PyTypeObject PyObjectPlus::Type = { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | #if (PY_VERSION_HEX >= 0x02060000)
 | 
					
						
							|  |  |  | 	PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	/* python 2.5 and below */ | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	0,				/*ob_size*/ | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	"PyObjectPlus",			/*tp_name*/ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	sizeof(PyObjectPlus_Proxy),		/*tp_basicsize*/ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	0,				/*tp_itemsize*/ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	py_base_dealloc, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	py_base_repr, | 
					
						
							|  |  |  | 	0,0,0,0,0,0, | 
					
						
							|  |  |  | 	py_base_getattro, | 
					
						
							|  |  |  | 	py_base_setattro, | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0,0,0, | 
					
						
							|  |  |  | 	Methods | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-20 09:13:06 +00:00
										 |  |  | PyObjectPlus::~PyObjectPlus() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	if(m_proxy) { | 
					
						
							|  |  |  | 		Py_DECREF(m_proxy);			/* Remove own reference, python may still have 1 */ | 
					
						
							|  |  |  | 		BGE_PROXY_REF(m_proxy)= NULL; | 
					
						
							| 
									
										
										
										
											2006-01-30 20:33:59 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-12-20 09:13:06 +00:00
										 |  |  | //	assert(ob_refcnt==0);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | void PyObjectPlus::py_base_dealloc(PyObject *self)				// python wrapper
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus) { | 
					
						
							|  |  |  | 		if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it  */ | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			delete self_plus; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BGE_PROXY_REF(self)= NULL; // not really needed
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList()				// constructor
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-03-25 10:33:39 +00:00
										 |  |  | 	MT_assert(T != NULL); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	m_proxy= NULL; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | }; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Methods 	-- Every class, even the abstract one should have a Methods | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyMethodDef PyObjectPlus::Methods[] = { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  |   {"isA",		 (PyCFunction) sPyisA,			METH_O}, | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   {NULL, NULL}		/* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyAttributeDef PyObjectPlus::Attributes[] = { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("invalid",		PyObjectPlus, pyattr_get_invalid), | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	{NULL} //Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | {	 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 	Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Parents		-- Every class, even the abstract one should have parents | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus attributes	-- attributes | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ | 
					
						
							|  |  |  | PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus==NULL) { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		if(!strcmp("invalid", PyString_AsString(attr))) { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			Py_RETURN_TRUE; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	PyObject *ret= self_plus->py_getattro(attr); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */ | 
					
						
							|  |  |  | 	if(ret==NULL) { | 
					
						
							|  |  |  | 		char *attr_str= PyString_AsString(attr); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (strcmp(attr_str, "__dict__")==0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* the error string will probably not
 | 
					
						
							|  |  |  | 			 * be set but just incase clear it */ | 
					
						
							|  |  |  | 			PyErr_Clear();  | 
					
						
							|  |  |  | 			ret= self_plus->py_getattro_dict(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (!PyErr_Occurred()) { | 
					
						
							|  |  |  | 			/* We looked for an attribute but it wasnt found
 | 
					
						
							|  |  |  | 			 * since py_getattro didnt set the error, set it here */ | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ | 
					
						
							|  |  |  | int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus==NULL) { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (value==NULL) | 
					
						
							|  |  |  | 		return self_plus->py_delattro(attr); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return self_plus->py_setattro(attr, value);  | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-05-21 09:18:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *PyObjectPlus::py_base_repr(PyObject *self)			// This should be the entry in Type.
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus==NULL) { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return self_plus->py_repr();   | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *PyObjectPlus::py_getattro(PyObject* attr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ | 
					
						
							|  |  |  | 	if (descr == NULL) { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		/* Copied from py_getattro_up */ | 
					
						
							|  |  |  | 		if (PyCObject_Check(descr)) { | 
					
						
							|  |  |  | 			return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); | 
					
						
							|  |  |  | 		} else if (descr->ob_type->tp_descr_get) { | 
					
						
							|  |  |  | 			return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		/* end py_getattro_up copy */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | PyObject* PyObjectPlus::py_getattro_dict() { | 
					
						
							|  |  |  | 	return py_getattr_dict(NULL, Type.tp_dict); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | int PyObjectPlus::py_delattro(PyObject* 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-04-20 15:06:46 +00:00
										 |  |  | int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-09-03 06:43:07 +00:00
										 |  |  | 	PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	return PY_SET_ATTR_MISSING; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// fake attribute, ignore
 | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// the attribute has no field correspondance, handover processing to function.
 | 
					
						
							|  |  |  | 		if (attrdef->m_getFunction == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		return (*attrdef->m_getFunction)(self, attrdef); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; | 
					
						
							|  |  |  | 	if (attrdef->m_length > 1) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		PyObject* resultlist = PyList_New(attrdef->m_length); | 
					
						
							|  |  |  | 		for (unsigned int i=0; i<attrdef->m_length; i++) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			switch (attrdef->m_type) { | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					bool *val = reinterpret_cast<bool*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(bool); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					short int *val = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(short int); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			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
 | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					int *val = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(int); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					float *val = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(float); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val)); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				// no support for array of complex data
 | 
					
						
							|  |  |  | 				Py_DECREF(resultlist); | 
					
						
							|  |  |  | 				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); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 			// enum are like int, just make sure the field size is the same
 | 
					
						
							|  |  |  | 			if (sizeof(int) != attrdef->m_size) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			// walkthrough
 | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				int *val = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 				return PyInt_FromLong(*val); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				float *val = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 				return PyFloat_FromDouble(*val); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_VECTOR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				PyObject* resultlist = PyList_New(3); | 
					
						
							|  |  |  | 				MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); | 
					
						
							|  |  |  | 				for (unsigned int i=0; i<3; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resultlist; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				STR_String *val = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 				return PyString_FromString(*val); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	void *undoBuffer = NULL; | 
					
						
							|  |  |  | 	void *sourceBuffer = NULL; | 
					
						
							|  |  |  | 	size_t bufferSize = 0; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; | 
					
						
							|  |  |  | 	if (attrdef->m_length > 1) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		if (!PySequence_Check(value))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (PySequence_Size(value) != attrdef->m_length) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		switch (attrdef->m_type)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_FUNCTION: | 
					
						
							|  |  |  | 			if (attrdef->m_setFunction == NULL)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			return (*attrdef->m_setFunction)(self, attrdef, value); | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 			bufferSize = sizeof(bool); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 			bufferSize = sizeof(short int); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 			bufferSize = sizeof(int); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 			bufferSize = sizeof(float); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			// should not happen
 | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// 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)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					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_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					short int *var = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(short int); | 
					
						
							|  |  |  | 					if (PyInt_Check(item))  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						long val = PyInt_AsLong(item); | 
					
						
							|  |  |  | 						if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 								val = attrdef->m_imin; | 
					
						
							|  |  |  | 							else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 								val = attrdef->m_imax; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						*var = (short int)val; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			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_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							|  |  |  | 					goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// walkthrough
 | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					int *var = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(int); | 
					
						
							|  |  |  | 					if (PyInt_Check(item))  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						long val = PyInt_AsLong(item); | 
					
						
							|  |  |  | 						if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 								val = attrdef->m_imin; | 
					
						
							|  |  |  | 							else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 								val = attrdef->m_imax; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 							goto UNDO_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						*var = (int)val; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					float *var = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 					ptr += sizeof(float); | 
					
						
							|  |  |  | 					double val = PyFloat_AsDouble(item); | 
					
						
							|  |  |  | 					if (val == -1.0 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					else if (attrdef->m_clamp)  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						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_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					*var = (float)val; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				// should not happen
 | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							|  |  |  | 				goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// no error, call check function if any
 | 
					
						
							|  |  |  | 		if (attrdef->m_checkFunction != NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((*attrdef->m_checkFunction)(self, attrdef) != 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				// if the checing function didnt set an error then set a generic one here so we dont set an error with no exception
 | 
					
						
							|  |  |  | 				if (PyErr_Occurred()==0) | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", reasion unknown", attrdef->m_name); | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				// post check returned an error, restore values
 | 
					
						
							|  |  |  | 			UNDO_AND_ERROR: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				if (undoBuffer) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					memcpy(sourceBuffer, undoBuffer, bufferSize); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					free(undoBuffer); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (undoBuffer) | 
					
						
							|  |  |  | 			free(undoBuffer); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		return PY_SET_ATTR_SUCCESS; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else	// simple attribute value
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (attrdef->m_setFunction == NULL) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			return (*attrdef->m_setFunction)(self, attrdef, value); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		if (attrdef->m_checkFunction != NULL || attrdef->m_type == KX_PYATTRIBUTE_TYPE_VECTOR) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// post check function is provided, prepare undo buffer
 | 
					
						
							|  |  |  | 			sourceBuffer = ptr; | 
					
						
							|  |  |  | 			switch (attrdef->m_type)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 				bufferSize = sizeof(bool); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 				bufferSize = sizeof(short); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_VECTOR: | 
					
						
							|  |  |  | 				bufferSize = sizeof(MT_Vector3); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				return PY_SET_ATTR_FAIL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			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_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				short int *var = reinterpret_cast<short int*>(ptr); | 
					
						
							|  |  |  | 				if (PyInt_Check(value))  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					long val = PyInt_AsLong(value); | 
					
						
							|  |  |  | 					if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 							val = attrdef->m_imin; | 
					
						
							|  |  |  | 						else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 							val = attrdef->m_imax; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					*var = (short int)val; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		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_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							|  |  |  | 				goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// walkthrough
 | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int *var = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 				if (PyInt_Check(value))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					long val = PyInt_AsLong(value); | 
					
						
							|  |  |  | 					if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						if (val < attrdef->m_imin) | 
					
						
							|  |  |  | 							val = attrdef->m_imin; | 
					
						
							|  |  |  | 						else if (val > attrdef->m_imax) | 
					
						
							|  |  |  | 							val = attrdef->m_imax; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					*var = (int)val; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				float *var = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 				double val = PyFloat_AsDouble(value); | 
					
						
							|  |  |  | 				if (val == -1.0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if (attrdef->m_clamp) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					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_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				*var = (float)val; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_VECTOR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (!PySequence_Check(value) || PySequence_Size(value) != 3)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr); | 
					
						
							|  |  |  | 				for (int i=0; i<3; 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); | 
					
						
							|  |  |  | 					double val = PyFloat_AsDouble(item); | 
					
						
							|  |  |  | 					if (val == -1.0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto RESTORE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else if (attrdef->m_clamp) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						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_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto RESTORE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					(*var)[i] = (MT_Scalar)val; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				STR_String *var = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 				if (PyString_Check(value))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					char *val = PyString_AsString(value); | 
					
						
							|  |  |  | 					if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						if (strlen(val) < attrdef->m_imin) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							// can't increase the length of the string
 | 
					
						
							|  |  |  | 							PyErr_Format(PyExc_ValueError, "string length too short for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						else if (strlen(val) > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							// trim the string
 | 
					
						
							|  |  |  | 							char c = val[attrdef->m_imax]; | 
					
						
							|  |  |  | 							val[attrdef->m_imax] = 0; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 							*var = val; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 							val[attrdef->m_imax] = c; | 
					
						
							|  |  |  | 							break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_ValueError, "string length out of range for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					*var = val; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected a string for attribute \"%s\"", attrdef->m_name); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			// should not happen
 | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name); | 
					
						
							|  |  |  | 			goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// check if post processing is needed
 | 
					
						
							|  |  |  | 	if (attrdef->m_checkFunction != NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if ((*attrdef->m_checkFunction)(self, attrdef) != 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// restore value
 | 
					
						
							|  |  |  | 		RESTORE_AND_ERROR: | 
					
						
							|  |  |  | 			if (undoBuffer) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					// 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); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		FREE_AND_ERROR: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			if (undoBuffer) | 
					
						
							|  |  |  | 				free(undoBuffer); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			return 1; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	if (undoBuffer) | 
					
						
							|  |  |  | 		free(undoBuffer); | 
					
						
							|  |  |  | 	return 0;	 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus repr		-- representations | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *PyObjectPlus::py_repr(void) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											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"
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 	PyParentObject  P; | 
					
						
							|  |  |  | 	PyParentObject *Ps = GetParents(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (P = Ps[i=0]; P != NULL; P = Ps[i++]) | 
					
						
							|  |  |  | 		if (P==T) | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool PyObjectPlus::isA(const char *mytypename)		// check typename of each parent
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 	PyParentObject  P; | 
					
						
							|  |  |  | 	PyParentObject *Ps = GetParents(); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	for (P = Ps[i=0]; P != NULL; P = Ps[i++]) | 
					
						
							|  |  |  | 		if (strcmp(P->tp_name, mytypename)==0) | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *PyObjectPlus::PyisA(PyObject *value)		// Python wrapper for isA
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	if (PyType_Check(value)) { | 
					
						
							|  |  |  | 		return PyBool_FromLong(isA((PyTypeObject *)value)); | 
					
						
							|  |  |  | 	} else if (PyString_Check(value)) { | 
					
						
							|  |  |  | 		return PyBool_FromLong(isA(PyString_AsString(value))); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string"); | 
					
						
							|  |  |  |     return NULL;	 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void PyObjectPlus::ProcessReplica() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Clear the proxy, will be created again if needed with GetProxy()
 | 
					
						
							|  |  |  | 	 * otherwise the PyObject will point to the wrong reference */ | 
					
						
							|  |  |  | 	m_proxy= NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Sometimes we might want to manually invalidate a BGE type even if
 | 
					
						
							|  |  |  |  * it hasnt been released by the BGE, say for example when an object | 
					
						
							|  |  |  |  * is removed from a scene, accessing it may cause problems. | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * In this case the current proxy is made invalid, disowned, | 
					
						
							|  |  |  |  * and will raise an error on access. However if python can get access | 
					
						
							|  |  |  |  * to this class again it will make a new proxy and work as expected. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void PyObjectPlus::InvalidateProxy()		// check typename of each parent
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_proxy) {  | 
					
						
							|  |  |  | 		BGE_PROXY_REF(m_proxy)=NULL; | 
					
						
							|  |  |  | 		Py_DECREF(m_proxy); | 
					
						
							|  |  |  | 		m_proxy= NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | /* Utility function called by the macro py_getattro_up()
 | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  |  * for getting ob.__dict__() values from our PyObject | 
					
						
							|  |  |  |  * this is used by python for doing dir() on an object, so its good | 
					
						
							|  |  |  |  * if we return a list of attributes and methods. | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * Other then making dir() useful the value returned from __dict__() is not useful | 
					
						
							|  |  |  |  * since every value is a Py_None | 
					
						
							|  |  |  |  * */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict) | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */ | 
					
						
							|  |  |  |     	PyErr_Clear(); | 
					
						
							|  |  |  |     	pydict = PyDict_New(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	PyDict_Update(pydict, tp_dict); | 
					
						
							|  |  |  | 	return pydict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (self->m_proxy==NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp); | 
					
						
							|  |  |  | 		BGE_PROXY_PYOWNS(self->m_proxy) = false; | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	//PyObject_Print(self->m_proxy, stdout, 0);
 | 
					
						
							|  |  |  | 	//printf("ref %d\n", self->m_proxy->ob_refcnt);
 | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	BGE_PROXY_REF(self->m_proxy) = self; /* Its possible this was set to NULL, so set it back here */ | 
					
						
							|  |  |  | 	Py_INCREF(self->m_proxy); /* we own one, thos ones fore the return */ | 
					
						
							|  |  |  | 	return self->m_proxy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (self->m_proxy) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(py_owns) | 
					
						
							|  |  |  | 		{	/* Free */ | 
					
						
							|  |  |  | 			BGE_PROXY_REF(self->m_proxy) = NULL; | 
					
						
							|  |  |  | 			Py_DECREF(self->m_proxy); | 
					
						
							|  |  |  | 			self->m_proxy= NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			Py_INCREF(self->m_proxy); | 
					
						
							|  |  |  | 			return self->m_proxy; | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	GetProxy_Ext(self, tp); | 
					
						
							|  |  |  | 	if(py_owns) { | 
					
						
							|  |  |  | 		BGE_PROXY_PYOWNS(self->m_proxy) = py_owns; | 
					
						
							|  |  |  | 		Py_DECREF(self->m_proxy); /* could avoid thrashing here but for now its ok */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return self->m_proxy; | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | /* deprecation warning management */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool PyObjectPlus::m_ignore_deprecation_warnings(false); | 
					
						
							|  |  |  | void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_ignore_deprecation_warnings = ignoreDeprecationWarnings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		PyObject *getframe, *frame; | 
					
						
							|  |  |  | 		PyObject *f_lineno, *f_code, *co_filename; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		getframe = PySys_GetObject((char *)"_getframe"); // borrowed
 | 
					
						
							|  |  |  | 		if (getframe) { | 
					
						
							|  |  |  | 			frame = PyObject_CallObject(getframe, NULL); | 
					
						
							|  |  |  | 			if (frame) { | 
					
						
							|  |  |  | 				f_lineno= PyObject_GetAttrString(frame, "f_lineno"); | 
					
						
							|  |  |  | 				f_code= PyObject_GetAttrString(frame, "f_code"); | 
					
						
							|  |  |  | 				if (f_lineno && f_code) { | 
					
						
							|  |  |  | 					co_filename= PyObject_GetAttrString(f_code, "co_filename"); | 
					
						
							|  |  |  | 					if (co_filename) { | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						Py_DECREF(f_lineno); | 
					
						
							|  |  |  | 						Py_DECREF(f_code); | 
					
						
							|  |  |  | 						Py_DECREF(co_filename); | 
					
						
							|  |  |  | 						Py_DECREF(frame); | 
					
						
							|  |  |  | 						return; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				Py_XDECREF(f_lineno); | 
					
						
							|  |  |  | 				Py_XDECREF(f_code); | 
					
						
							|  |  |  | 				Py_DECREF(frame); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PyObjectPlus::ClearDeprecationWarning() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	WarnLink *wlink_next; | 
					
						
							|  |  |  | 	WarnLink *wlink = GetDeprecationWarningLinkFirst(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	while(wlink) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */ | 
					
						
							|  |  |  | 		wlink_next= reinterpret_cast<WarnLink *>(wlink->link); | 
					
						
							|  |  |  | 		wlink->link= NULL; | 
					
						
							|  |  |  | 		wlink= wlink_next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	NullDeprecationWarning(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WarnLink*		m_base_wlink_first= NULL; | 
					
						
							|  |  |  | WarnLink*		m_base_wlink_last= NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WarnLink*		PyObjectPlus::GetDeprecationWarningLinkFirst(void) {return m_base_wlink_first;} | 
					
						
							|  |  |  | WarnLink*		PyObjectPlus::GetDeprecationWarningLinkLast(void) {return m_base_wlink_last;} | 
					
						
							|  |  |  | void			PyObjectPlus::SetDeprecationWarningFirst(WarnLink* wlink) {m_base_wlink_first= wlink;} | 
					
						
							|  |  |  | void			PyObjectPlus::SetDeprecationWarningLinkLast(WarnLink* wlink) {m_base_wlink_last= wlink;} | 
					
						
							|  |  |  | void			PyObjectPlus::NullDeprecationWarning() {m_base_wlink_first= m_base_wlink_last= NULL;} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #endif //NO_EXP_PYTHON_EMBEDDING
 | 
					
						
							|  |  |  | 
 |