| 
									
										
										
										
											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 | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | PyTypeObject PyObjectPlus::Type = { | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | 	PyObject_HEAD_INIT(NULL) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	0,				/*ob_size*/ | 
					
						
							|  |  |  | 	"PyObjectPlus",			/*tp_name*/ | 
					
						
							| 
									
										
										
										
											2009-04-19 14:57:52 +00:00
										 |  |  | 	sizeof(PyObjectPlus_Proxy),		/*tp_basicsize*/ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	0,				/*tp_itemsize*/ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							| 
									
										
										
										
											2009-04-19 14:57:52 +00:00
										 |  |  | 	py_base_dealloc, | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | 	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, | 
					
						
							| 
									
										
										
										
											2009-04-03 04:12:20 +00:00
										 |  |  | 	Methods | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-20 09:13:06 +00:00
										 |  |  | PyObjectPlus::~PyObjectPlus() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +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-19 14:57:52 +00:00
										 |  |  | void PyObjectPlus::py_base_dealloc(PyObject *self)				// python wrapper
 | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus) { | 
					
						
							|  |  |  | 		if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it  */ | 
					
						
							|  |  |  | 			delete self_plus; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BGE_PROXY_REF(self)= NULL; // not really needed
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +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-19 14:57:52 +00:00
										 |  |  |   {"isA",		 (PyCFunction) sPyisA,			METH_O}, | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   {NULL, NULL}		/* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | PyAttributeDef PyObjectPlus::Attributes[] = { | 
					
						
							| 
									
										
										
										
											2009-04-17 20:06:06 +00:00
										 |  |  | 	KX_PYATTRIBUTE_RO_FUNCTION("isValid",		PyObjectPlus, pyattr_get_is_valid), | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 	{NULL} //Sentinel
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 20:06:06 +00:00
										 |  |  | PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							|  |  |  | {	 | 
					
						
							|  |  |  | 	Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-19 14:57:52 +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) { | 
					
						
							|  |  |  | 		if(!strcmp("isValid", PyString_AsString(attr))) { | 
					
						
							|  |  |  | 			Py_RETURN_TRUE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return self_plus->py_getattro(attr);  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 	if(self_plus==NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (value==NULL) | 
					
						
							|  |  |  | 		return self_plus->py_delattro(attr); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return self_plus->py_setattro(attr, value);  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return self_plus->py_repr();   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | PyObject *PyObjectPlus::py_getattro(PyObject* attr) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | 	PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ | 
					
						
							|  |  |  | 	if (descr == NULL) { | 
					
						
							| 
									
										
										
										
											2009-04-04 09:54:05 +00:00
										 |  |  | 		if (strcmp(PyString_AsString(attr), "__dict__")==0) { | 
					
						
							| 
									
										
										
										
											2009-04-07 16:00:32 +00:00
										 |  |  | 			return py_getattr_dict(NULL, Type.tp_dict); /* no Attributes yet */ | 
					
						
							| 
									
										
										
										
											2009-04-04 09:54:05 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-04-17 20:06:06 +00:00
										 |  |  | 		PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr)); | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-04-17 20:06:06 +00:00
										 |  |  | 		/* 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) { | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +00:00
										 |  |  | 			return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); | 
					
						
							| 
									
										
										
										
											2009-04-17 20:06:06 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)"); | 
					
						
							|  |  |  | 			return descr; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* end py_getattro_up copy */ | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +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-03 14:51:06 +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-12 09:56:30 +00:00
										 |  |  | 	return PY_SET_ATTR_MISSING; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 	if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 		// 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) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		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-07 11:06:35 +00:00
										 |  |  | 			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; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			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); | 
					
						
							|  |  |  | 					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
 | 
					
						
							|  |  |  | 				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-07 11:06:35 +00:00
										 |  |  | 			// walkthrough
 | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				int *val = reinterpret_cast<int*>(ptr); | 
					
						
							|  |  |  | 				return PyInt_FromLong(*val); | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				float *val = reinterpret_cast<float*>(ptr); | 
					
						
							|  |  |  | 				return PyFloat_FromDouble(*val); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				STR_String *val = reinterpret_cast<STR_String*>(ptr); | 
					
						
							|  |  |  | 				return PyString_FromString(*val); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 		if (!PySequence_Check(value))  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			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_FUNCTION: | 
					
						
							|  |  |  | 			if (attrdef->m_setFunction == NULL)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				PyErr_SetString(PyExc_AttributeError, "function attribute without function, report to blender.org"); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				return 1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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_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)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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)) | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						*var = (item == Py_True); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 						long val = PyInt_AsLong(item); | 
					
						
							|  |  |  | 						if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 						else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 							PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						*var = (short int)val; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 						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_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); | 
					
						
							|  |  |  | 					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-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 						else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 							PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							|  |  |  | 							goto UNDO_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						*var = (int)val; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 						PyErr_SetString(PyExc_TypeError, "expected a float"); | 
					
						
							|  |  |  | 						goto UNDO_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; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					else if (val < attrdef->m_fmin || val > attrdef->m_fmax) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_ValueError, "item value out of range"); | 
					
						
							|  |  |  | 						goto UNDO_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					*var = (float)val; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			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_checkFunction != NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((*attrdef->m_checkFunction)(self, attrdef) != 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// post check returned an error, restore values
 | 
					
						
							|  |  |  | 			UNDO_AND_ERROR: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				if (undoBuffer) | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					memcpy(sourceBuffer, undoBuffer, bufferSize); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					free(undoBuffer); | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				return 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (undoBuffer) | 
					
						
							|  |  |  | 			free(undoBuffer); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else	// simple attribute value
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (attrdef->m_setFunction == NULL) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_AttributeError, "function attribute without function, report to blender.org"); | 
					
						
							|  |  |  | 				return 1; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			return (*attrdef->m_setFunction)(self, attrdef, value); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (attrdef->m_checkFunction != NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// post check function is provided, prepare undo buffer
 | 
					
						
							|  |  |  | 			sourceBuffer = ptr; | 
					
						
							|  |  |  | 			switch (attrdef->m_type)  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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; | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); | 
					
						
							|  |  |  | 				return 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (bufferSize) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				undoBuffer = malloc(bufferSize); | 
					
						
							|  |  |  | 				if (undoBuffer) | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					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); | 
					
						
							| 
									
										
										
										
											2009-03-22 21:36:48 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					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); | 
					
						
							|  |  |  | 					if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 					else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						PyErr_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					*var = (short int)val; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					PyErr_SetString(PyExc_TypeError, "expected an integer"); | 
					
						
							|  |  |  | 					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_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); | 
					
						
							|  |  |  | 				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-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 					else if (val < attrdef->m_imin || val > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						PyErr_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					*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); | 
					
						
							|  |  |  | 				double val = PyFloat_AsDouble(value); | 
					
						
							|  |  |  | 				if (val == -1.0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, "expected a float"); | 
					
						
							|  |  |  | 					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_SetString(PyExc_ValueError, "value out of range"); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				*var = (float)val; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		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-07 11:06:35 +00:00
										 |  |  | 						if (strlen(val) < attrdef->m_imin) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 							// can't increase the length of the string
 | 
					
						
							|  |  |  | 							PyErr_SetString(PyExc_ValueError, "string length too short"); | 
					
						
							| 
									
										
										
										
											2009-01-02 17:43:56 +00:00
										 |  |  | 							goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 						else if (strlen(val) > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 							val[attrdef->m_imax] = c; | 
					
						
							|  |  |  | 							break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_SetString(PyExc_ValueError, "string length out of range"); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 					*var = val; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, "expected a string"); | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 		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_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-07 11:06:35 +00:00
										 |  |  | 				if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +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-07 11:06:35 +00:00
										 |  |  | 		FREE_AND_ERROR: | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			if (undoBuffer) | 
					
						
							|  |  |  | 				free(undoBuffer); | 
					
						
							| 
									
										
										
										
											2009-04-07 11:06:35 +00:00
										 |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (undoBuffer) | 
					
						
							|  |  |  | 		free(undoBuffer); | 
					
						
							|  |  |  | 	return 0;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus repr		-- representations | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +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-04 08:20:52 +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-04 08:20:52 +00:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 	PyParentObject  P; | 
					
						
							|  |  |  | 	PyParentObject *Ps = GetParents(); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2009-04-04 08:20:52 +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-19 14:57:52 +00:00
										 |  |  | PyObject *PyObjectPlus::PyisA(PyObject *self, PyObject *value)		// Python wrapper for isA
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-04 08:20:52 +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, "expected a type or a string"); | 
					
						
							|  |  |  |     return NULL;	 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-03 14:51:06 +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-07 16:00:32 +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-07 16:00:32 +00:00
										 |  |  | 	PyDict_Update(pydict, tp_dict); | 
					
						
							| 
									
										
										
										
											2009-02-26 09:04:06 +00:00
										 |  |  | 	return pydict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-19 12:46:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	//PyObject_Print(self->m_proxy, stdout, 0);
 | 
					
						
							|  |  |  | 	//printf("ref %d\n", self->m_proxy->ob_refcnt);
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #endif //NO_EXP_PYTHON_EMBEDDING
 | 
					
						
							|  |  |  | 
 |