| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 13:31:23 +00:00
										 |  |  | /** \file gameengine/Expressions/PyObjectPlus.cpp
 | 
					
						
							|  |  |  |  *  \ingroup expressions | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * 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
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							| 
									
										
										
										
											2011-03-09 01:25:59 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2011-03-09 02:06:21 +00:00
										 |  |  | #include <stddef.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "PyObjectPlus.h"
 | 
					
						
							|  |  |  | #include "STR_String.h"
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | #include "MT_Vector3.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObjectPlus::~PyObjectPlus() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 	if(m_proxy) { | 
					
						
							|  |  |  | 		BGE_PROXY_REF(m_proxy)= NULL; | 
					
						
							|  |  |  | 		Py_DECREF(m_proxy);			/* Remove own reference, python may still have 1 */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | //	assert(ob_refcnt==0);
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObjectPlus::PyObjectPlus() : SG_QList()				// constructor
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 	m_proxy= NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PyObjectPlus::ProcessReplica() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 	/* Clear the proxy, will be created again if needed with GetProxy()
 | 
					
						
							|  |  |  | 	 * otherwise the PyObject will point to the wrong reference */ | 
					
						
							|  |  |  | 	m_proxy= NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 	if(m_proxy) { | 
					
						
							|  |  |  | 		BGE_PROXY_REF(m_proxy)=NULL; | 
					
						
							|  |  |  | 		Py_DECREF(m_proxy); | 
					
						
							|  |  |  | 		m_proxy= NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #ifdef WITH_PYTHON
 | 
					
						
							| 
									
										
										
										
											2009-09-29 21:42:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | 	"PyObjectPlus",					/*tp_name*/ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	sizeof(PyObjectPlus_Proxy),		/*tp_basicsize*/ | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | 	0,								/*tp_itemsize*/ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 	/* methods */ | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | 	py_base_dealloc,				/* tp_dealloc */ | 
					
						
							|  |  |  | 	0,								/* printfunc tp_print; */ | 
					
						
							|  |  |  | 	0,								/* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	0,								/* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	0,								/* tp_compare */ /* DEPRECATED in python 3.0! */ | 
					
						
							|  |  |  | 	py_base_repr,					/* tp_repr */ | 
					
						
							|  |  |  | 	0,0,0,0,0,0,0,0,0,				/* Method suites for standard classes */ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* long tp_flags; */ | 
					
						
							|  |  |  | 	0,0,0,0, | 
					
						
							|  |  |  | 	/* weak reference enabler */ | 
					
						
							|  |  |  | #ifdef USE_WEAKREFS
 | 
					
						
							|  |  |  | 	offsetof(PyObjectPlus_Proxy, in_weakreflist),	/* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	0, | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 	0,0, | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | 	Methods, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	NULL // no subtype
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-29 12: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) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return self_plus->py_repr();   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *base_type; | 
					
						
							|  |  |  | 	PyObjectPlus_Proxy *base = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the 'base' PyObject may be subclassed (multiple times even)
 | 
					
						
							|  |  |  | 	 * we need to find the first C++ defined class to check 'type' | 
					
						
							|  |  |  | 	 * is a subclass of the base arguments type. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * This way we can share one tp_new function for every PyObjectPlus | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * eg. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * # CustomOb is called 'type' in this C code | 
					
						
							|  |  |  | 	 * class CustomOb(GameTypes.KX_GameObject): | 
					
						
							|  |  |  | 	 *     pass | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type | 
					
						
							|  |  |  | 	 * ob = CustomOb(cont.owner) | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * */ | 
					
						
							|  |  |  | 	base_type= Py_TYPE(base); | 
					
						
							|  |  |  | 	while(base_type && !BGE_PROXY_CHECK_TYPE(base_type)) | 
					
						
							|  |  |  | 		base_type= base_type->tp_base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(base_type==NULL || !BGE_PROXY_CHECK_TYPE(base_type)) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, "can't subclass from a blender game type because the argument given is not a game class or subclass"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-28 13:11:24 +00:00
										 |  |  | 	/* use base_type rather than Py_TYPE(base) because we could already be subtyped */ | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | 	if(!PyType_IsSubtype(type, base_type)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, "can't subclass blender game type <%s> from <%s> because it is not a subclass", base_type->tp_name, type->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* invalidate the existing base and return a new subclassed one,
 | 
					
						
							|  |  |  | 	 * this is a bit dodgy in that it also attaches its self to the existing object | 
					
						
							|  |  |  | 	 * which is not really 'correct' python OO but for our use its OK. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyObjectPlus_Proxy *ret = (PyObjectPlus_Proxy *) type->tp_alloc(type, 0); /* starts with 1 ref, used for the return ref' */ | 
					
						
							|  |  |  | 	ret->ref= base->ref; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ret->ptr= base->ptr; | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | 	ret->py_owns= base->py_owns; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ret->py_ref = base->py_ref; | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (ret->py_ref) { | 
					
						
							|  |  |  | 		base->ref= NULL;		/* invalidate! disallow further access */ | 
					
						
							|  |  |  | 		base->ptr = NULL; | 
					
						
							|  |  |  | 		if (ret->ref) | 
					
						
							|  |  |  | 			ret->ref->m_proxy= NULL; | 
					
						
							|  |  |  | 		/* 'base' may be free'd after this func finished but not necessarily
 | 
					
						
							|  |  |  | 		 * there is no reference to the BGE data now so it will throw an error on access */ | 
					
						
							|  |  |  | 		Py_DECREF(base); | 
					
						
							|  |  |  | 		if (ret->ref) { | 
					
						
							|  |  |  | 			ret->ref->m_proxy= (PyObject *)ret; /* no need to add a ref because one is added when creating. */ | 
					
						
							|  |  |  | 			Py_INCREF(ret); /* we return a new ref but m_proxy holds a ref so we need to add one */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// generic structures don't hold a reference to this proxy, so don't increment ref count
 | 
					
						
							|  |  |  | 		if (ret->py_owns) | 
					
						
							|  |  |  | 			// but if the proxy owns the structure, there can be only one owner
 | 
					
						
							|  |  |  | 			base->ptr= NULL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (PyObject *)ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   * @param self A PyObjectPlus_Proxy | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | void PyObjectPlus::py_base_dealloc(PyObject *self)				// python wrapper
 | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | #ifdef USE_WEAKREFS
 | 
					
						
							|  |  |  | 	if (BGE_PROXY_WKREF(self) != NULL) | 
					
						
							|  |  |  | 		PyObject_ClearWeakRefs((PyObject *) self); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (BGE_PROXY_PYREF(self)) { | 
					
						
							|  |  |  | 		PyObjectPlus *self_plus= BGE_PROXY_REF(self); | 
					
						
							|  |  |  | 		if(self_plus) { | 
					
						
							|  |  |  | 			if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it  */ | 
					
						
							|  |  |  | 				self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ | 
					
						
							|  |  |  | 				delete self_plus; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			BGE_PROXY_REF(self)= NULL; // not really needed
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// the generic pointer is not deleted directly, only through self_plus
 | 
					
						
							|  |  |  | 		BGE_PROXY_PTR(self)= NULL; // not really needed
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		void *ptr= BGE_PROXY_PTR(self); | 
					
						
							|  |  |  | 		if(ptr) { | 
					
						
							|  |  |  | 			if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it  */ | 
					
						
							|  |  |  | 				// generic structure owned by python MUST be created though MEM_alloc
 | 
					
						
							|  |  |  | 				MEM_freeN(ptr); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			BGE_PROXY_PTR(self)= NULL; // not really needed
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 	/* is ok normally but not for subtyping, use tp_free instead. */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	PyObject_DEL( self ); | 
					
						
							| 
									
										
										
										
											2009-06-29 12:06:46 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	Py_TYPE(self)->tp_free(self); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /*------------------------------
 | 
					
						
							|  |  |  |  * PyObjectPlus Methods 	-- Every class, even the abstract one should have a Methods | 
					
						
							|  |  |  | ------------------------------*/ | 
					
						
							|  |  |  | PyMethodDef PyObjectPlus::Methods[] = { | 
					
						
							|  |  |  |   {NULL, NULL}		/* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | #define attr_invalid (&(PyObjectPlus::Attributes[0]))
 | 
					
						
							| 
									
										
										
										
											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-28 11:22:26 +00:00
										 |  |  | PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-13 20:08:57 +00:00
										 |  |  | 	return PyBool_FromLong(self_v ? 0:1); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | /* note, this is called as a python 'getset, where the PyAttributeDef is the closure */ | 
					
						
							|  |  |  | PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	PyObjectPlus *ref= (BGE_PROXY_REF(self_py)); | 
					
						
							|  |  |  | 	char* ptr = (attrdef->m_usePtr) ? (char*)BGE_PROXY_PTR(self_py) : (char*)ref; | 
					
						
							|  |  |  | 	if(ptr == NULL || (BGE_PROXY_PYREF(self_py) && (ref==NULL || !ref->py_is_valid()))) { | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | 		if(attrdef == attr_invalid) | 
					
						
							|  |  |  | 			Py_RETURN_TRUE; // dont bother running the function
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-11-22 10:19:19 +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; | 
					
						
							| 
									
										
										
										
											2010-07-24 09:26:05 +00:00
										 |  |  | 		return (*attrdef->m_getFunction)(ptr, attrdef); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ptr += attrdef->m_offset; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	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-29 02:25:54 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*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-29 02:25:54 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*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-29 02:25:54 +00:00
										 |  |  | 					PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*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) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_FLAG: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bool bval; | 
					
						
							|  |  |  | 				switch (attrdef->m_size) { | 
					
						
							|  |  |  | 				case 1: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned char *val = reinterpret_cast<unsigned char*>(ptr); | 
					
						
							|  |  |  | 						bval = (*val & attrdef->m_imin); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case 2: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned short *val = reinterpret_cast<unsigned short*>(ptr); | 
					
						
							|  |  |  | 						bval = (*val & attrdef->m_imin); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case 4: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned int *val = reinterpret_cast<unsigned int*>(ptr); | 
					
						
							|  |  |  | 						bval = (*val & attrdef->m_imin); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (attrdef->m_imax) | 
					
						
							|  |  |  | 					bval = !bval; | 
					
						
							|  |  |  | 				return PyLong_FromSsize_t(bval); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_BOOL: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bool *val = reinterpret_cast<bool*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				return PyLong_FromSsize_t(*val); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				short int *val = reinterpret_cast<short int*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				return PyLong_FromSsize_t(*val); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case KX_PYATTRIBUTE_TYPE_ENUM: | 
					
						
							|  |  |  | 			// enum are like int, just make sure the field size is the same
 | 
					
						
							|  |  |  | 			if (sizeof(int) != attrdef->m_size) | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				return PyLong_FromSsize_t(*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); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				if (attrdef->m_imin == 0) { | 
					
						
							|  |  |  | 					if (attrdef->m_imax == 0) { | 
					
						
							|  |  |  | 						return PyFloat_FromDouble(*val); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						// vector, verify size
 | 
					
						
							|  |  |  | 						if (attrdef->m_size != attrdef->m_imax*sizeof(float))  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							return NULL; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | #ifdef USE_MATHUTILS
 | 
					
						
							|  |  |  | 						return newVectorObject(val, attrdef->m_imax, Py_NEW, NULL); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 						PyObject* resultlist = PyList_New(attrdef->m_imax); | 
					
						
							|  |  |  | 						for (unsigned int i=0; i<attrdef->m_imax; i++) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(val[i])); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return resultlist; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					// matrix case
 | 
					
						
							|  |  |  | 					if (attrdef->m_size != attrdef->m_imax*attrdef->m_imin*sizeof(float))  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						return NULL; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | #ifdef USE_MATHUTILS
 | 
					
						
							|  |  |  | 					return newMatrixObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-12-23 09:55:34 +00:00
										 |  |  | 					PyObject* collist = PyList_New(attrdef->m_imin); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					for (unsigned int i=0; i<attrdef->m_imin; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-12-23 09:55:34 +00:00
										 |  |  | 						PyObject* col = PyList_New(attrdef->m_imax); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 						for (unsigned int j=0; j<attrdef->m_imax; j++) | 
					
						
							|  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2009-12-23 09:55:34 +00:00
										 |  |  | 							PyList_SET_ITEM(col,j,PyFloat_FromDouble(val[j])); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-12-23 09:55:34 +00:00
										 |  |  | 						PyList_SET_ITEM(collist,i,col); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 						val += attrdef->m_imax; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-12-23 09:55:34 +00:00
										 |  |  | 					return collist; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_VECTOR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-25 10:11:37 +00:00
										 |  |  | #ifdef USE_MATHUTILS
 | 
					
						
							|  |  |  | 				float fval[3]= {(*val)[0], (*val)[1], (*val)[2]}; | 
					
						
							| 
									
										
										
										
											2009-06-30 00:42:17 +00:00
										 |  |  | 				return newVectorObject(fval, 3, Py_NEW, NULL); | 
					
						
							| 
									
										
										
										
											2009-06-25 10:11:37 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 				PyObject* resultlist = PyList_New(3); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				for (unsigned int i=0; i<3; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resultlist; | 
					
						
							| 
									
										
										
										
											2009-06-25 10:11:37 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				STR_String *val = reinterpret_cast<STR_String*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				return PyUnicode_FromString(*val); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_CHAR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				return PyUnicode_FromString(ptr); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static bool py_check_attr_float(float *var, PyObject *value, const PyAttributeDef *attrdef) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	double val = PyFloat_AsDouble(value); | 
					
						
							|  |  |  | 	if (val == -1.0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*var = (float)val; | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | /* note, this is called as a python getset */ | 
					
						
							|  |  |  | int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	PyObjectPlus *ref= (BGE_PROXY_REF(self_py)); | 
					
						
							|  |  |  | 	char* ptr = (attrdef->m_usePtr) ? (char*)BGE_PROXY_PTR(self_py) : (char*)ref; | 
					
						
							|  |  |  | 	if(ref==NULL || !ref->py_is_valid() || ptr==NULL) { | 
					
						
							| 
									
										
										
										
											2009-06-28 11:22:26 +00:00
										 |  |  | 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); | 
					
						
							|  |  |  | 		return PY_SET_ATTR_FAIL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 	void *undoBuffer = NULL; | 
					
						
							|  |  |  | 	void *sourceBuffer = NULL; | 
					
						
							|  |  |  | 	size_t bufferSize = 0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	PyObject *item = NULL;	// to store object that must be dereferenced in case of error
 | 
					
						
							|  |  |  | 	PyObject *list = NULL;	// to store object that must be dereferenced in case of error
 | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ptr += attrdef->m_offset; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	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-09-24 21:22:24 +00:00
										 |  |  | 			return (*attrdef->m_setFunction)(ref, attrdef, value); | 
					
						
							| 
									
										
										
										
											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 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++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			item = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					if (PyLong_Check(item))  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 						*var = (PyLong_AsSsize_t(item) != 0); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					}  | 
					
						
							|  |  |  | 					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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					if (PyLong_Check(item))  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 						long val = PyLong_AsSsize_t(item); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					if (PyLong_Check(item))  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 						long val = PyLong_AsSsize_t(item); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						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; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// finished using item, release
 | 
					
						
							|  |  |  | 			Py_DECREF(item); | 
					
						
							|  |  |  | 			item = NULL; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// no error, call check function if any
 | 
					
						
							|  |  |  | 		if (attrdef->m_checkFunction != NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if ((*attrdef->m_checkFunction)(ref, attrdef) != 0) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											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-09-24 21:22:24 +00:00
										 |  |  | 				if (item) | 
					
						
							|  |  |  | 					Py_DECREF(item); | 
					
						
							| 
									
										
										
										
											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-09-24 21:22:24 +00:00
										 |  |  | 			return (*attrdef->m_setFunction)(ref, attrdef, value); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_FLAG: | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_CHAR: | 
					
						
							|  |  |  | 				bufferSize = attrdef->m_size; | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 			case KX_PYATTRIBUTE_TYPE_INT: | 
					
						
							|  |  |  | 				bufferSize = sizeof(int); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case KX_PYATTRIBUTE_TYPE_FLOAT: | 
					
						
							|  |  |  | 				bufferSize = sizeof(float); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				if (attrdef->m_imax) | 
					
						
							|  |  |  | 					bufferSize *= attrdef->m_imax; | 
					
						
							|  |  |  | 				if (attrdef->m_imin) | 
					
						
							|  |  |  | 					bufferSize *= attrdef->m_imin; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				if (PyLong_Check(value))  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					*var = (PyLong_AsSsize_t(value) != 0); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				}  | 
					
						
							|  |  |  | 				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; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_FLAG: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bool bval; | 
					
						
							|  |  |  | 				if (PyLong_Check(value))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					bval = (PyLong_AsSsize_t(value) != 0); | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 				else if (PyBool_Check(value)) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					bval = (value == Py_True); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (attrdef->m_imax) | 
					
						
							|  |  |  | 					bval = !bval; | 
					
						
							|  |  |  | 				switch (attrdef->m_size) { | 
					
						
							|  |  |  | 				case 1: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned char *val = reinterpret_cast<unsigned char*>(ptr); | 
					
						
							|  |  |  | 						*val = (*val & ~attrdef->m_imin) | ((bval)?attrdef->m_imin:0); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case 2: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned short *val = reinterpret_cast<unsigned short*>(ptr); | 
					
						
							|  |  |  | 						*val = (*val & ~attrdef->m_imin) | ((bval)?attrdef->m_imin:0); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				case 4: | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						unsigned int *val = reinterpret_cast<unsigned int*>(ptr); | 
					
						
							|  |  |  | 						*val = (*val & ~attrdef->m_imin) | ((bval)?attrdef->m_imin:0); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "internal error: unsupported flag field \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_SHORT: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				short int *var = reinterpret_cast<short int*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				if (PyLong_Check(value))  | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					long val = PyLong_AsSsize_t(value); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					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); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				if (PyLong_Check(value))  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 					long val = PyLong_AsSsize_t(value); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					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); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				if (attrdef->m_imin != 0)  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					if (attrdef->m_size != attrdef->m_imin*attrdef->m_imax*sizeof(float))  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "internal error: incorrect field size for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (!PySequence_Check(value) || PySequence_Size(value) != attrdef->m_imin)  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "expected a sequence of [%d][%d] floats for attribute \"%s\"", attrdef->m_imin, attrdef->m_imax, attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					for (int i=0; i<attrdef->m_imin; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyObject *list = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							|  |  |  | 						if (!PySequence_Check(list) || PySequence_Size(list) != attrdef->m_imax)  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							PyErr_Format(PyExc_TypeError, "expected a sequence of [%d][%d] floats for attribute \"%s\"", attrdef->m_imin, attrdef->m_imax, attrdef->m_name); | 
					
						
							|  |  |  | 							goto RESTORE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						for (int j=0; j<attrdef->m_imax; j++) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							item = PySequence_GetItem(list, j); /* new ref */ | 
					
						
							|  |  |  | 							if (!py_check_attr_float(var, item, attrdef)) | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								PyErr_Format(PyExc_TypeError, "expected a sequence of [%d][%d] floats for attribute \"%s\"", attrdef->m_imin, attrdef->m_imax, attrdef->m_name); | 
					
						
							|  |  |  | 								goto RESTORE_AND_ERROR; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							Py_DECREF(item); | 
					
						
							|  |  |  | 							item = NULL; | 
					
						
							|  |  |  | 							++var; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						Py_DECREF(list); | 
					
						
							|  |  |  | 						list = NULL; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 				else if (attrdef->m_imax != 0)  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					if (attrdef->m_size != attrdef->m_imax*sizeof(float))  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "internal error: incorrect field size for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (!PySequence_Check(value) || PySequence_Size(value) != attrdef->m_imax)  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						PyErr_Format(PyExc_TypeError, "expected a sequence of [%d] floats for attribute \"%s\"", attrdef->m_imax, attrdef->m_name); | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					for (int i=0; i<attrdef->m_imax; i++) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						item = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							|  |  |  | 						if (!py_check_attr_float(var, item, attrdef)) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							goto RESTORE_AND_ERROR; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						Py_DECREF(item); | 
					
						
							|  |  |  | 						item = NULL; | 
					
						
							|  |  |  | 						++var; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 				else | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					if (!py_check_attr_float(var, value, attrdef)) | 
					
						
							|  |  |  | 						goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				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); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					goto FREE_AND_ERROR; | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr); | 
					
						
							|  |  |  | 				for (int i=0; i<3; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					item = PySequence_GetItem(value, i); /* new ref */ | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					double val = PyFloat_AsDouble(item); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 					Py_DECREF(item); | 
					
						
							|  |  |  | 					item = NULL; | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 					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-09-24 21:22:24 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_CHAR: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (PyUnicode_Check(value))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Py_ssize_t val_len; | 
					
						
							|  |  |  | 					char *val = _PyUnicode_AsStringAndSize(value, &val_len); | 
					
						
							|  |  |  | 					strncpy(ptr, val, attrdef->m_size); | 
					
						
							|  |  |  | 					ptr[attrdef->m_size-1] = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					PyErr_Format(PyExc_TypeError, "expected a string for attribute \"%s\"", attrdef->m_name); | 
					
						
							|  |  |  | 					goto FREE_AND_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		case KX_PYATTRIBUTE_TYPE_STRING: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				STR_String *var = reinterpret_cast<STR_String*>(ptr); | 
					
						
							| 
									
										
										
										
											2009-06-29 02:25:54 +00:00
										 |  |  | 				if (PyUnicode_Check(value))  | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2009-09-02 03:14:38 +00:00
										 |  |  | 					Py_ssize_t val_len; | 
					
						
							|  |  |  | 					char *val = _PyUnicode_AsStringAndSize(value, &val_len); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					if (attrdef->m_clamp) | 
					
						
							| 
									
										
										
										
											2008-12-31 20:35:20 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2009-09-02 03:14:38 +00:00
										 |  |  | 						if (val_len < 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-09-02 03:14:38 +00:00
										 |  |  | 						else if (val_len > 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-09-02 03:14:38 +00:00
										 |  |  | 					} else if (val_len < attrdef->m_imin || val_len > attrdef->m_imax) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 					{ | 
					
						
							|  |  |  | 						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) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if ((*attrdef->m_checkFunction)(ref, attrdef) != 0) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// 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-09-24 21:22:24 +00:00
										 |  |  | 			if (list) | 
					
						
							|  |  |  | 				Py_DECREF(list); | 
					
						
							|  |  |  | 			if (item) | 
					
						
							|  |  |  | 				Py_DECREF(item); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | PyObject *PyObjectPlus::GetProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, void *ptr) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (self->m_proxy==NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp); | 
					
						
							|  |  |  | 		BGE_PROXY_PYOWNS(self->m_proxy) = false; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		BGE_PROXY_PYREF(self->m_proxy) = true; | 
					
						
							| 
									
										
										
										
											2011-02-25 15:07:25 +00:00
										 |  |  | #ifdef USE_WEAKREFS
 | 
					
						
							| 
									
										
										
										
											2011-02-25 14:32:35 +00:00
										 |  |  | 		BGE_PROXY_WKREF(self->m_proxy) = NULL; | 
					
						
							| 
									
										
										
										
											2011-02-25 15:07:25 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	BGE_PROXY_PTR(self->m_proxy) = ptr; | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	Py_INCREF(self->m_proxy); /* we own one, thos ones fore the return */ | 
					
						
							|  |  |  | 	return self->m_proxy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | PyObject *PyObjectPlus::NewProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, void *ptr, bool py_owns) | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (!self)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// in case of proxy without reference to game object
 | 
					
						
							|  |  |  | 		PyObject* proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp); | 
					
						
							|  |  |  | 		BGE_PROXY_PYREF(proxy) = false; | 
					
						
							|  |  |  | 		BGE_PROXY_PYOWNS(proxy) = py_owns; | 
					
						
							|  |  |  | 		BGE_PROXY_REF(proxy) = NULL;  | 
					
						
							|  |  |  | 		BGE_PROXY_PTR(proxy) = ptr; | 
					
						
							| 
									
										
										
										
											2011-02-25 15:07:25 +00:00
										 |  |  | #ifdef USE_WEAKREFS
 | 
					
						
							| 
									
										
										
										
											2011-07-09 19:59:32 +00:00
										 |  |  | 		BGE_PROXY_WKREF(proxy) = NULL; | 
					
						
							| 
									
										
										
										
											2011-02-25 15:07:25 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		return proxy; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	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
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	GetProxyPlus_Ext(self, tp, ptr); | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | void PyDebugLine() | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | 	// 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) { | 
					
						
							| 
									
										
										
										
											2011-05-29 11:05:52 +00:00
										 |  |  | 				co_filename= ((PyCodeObject *)f_code)->co_filename; /* borrow */ | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | 				if (co_filename) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					printf("\t%s:%d\n", _PyUnicode_AsString(co_filename), (int)PyLong_AsSsize_t(f_lineno)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					Py_DECREF(f_lineno); | 
					
						
							|  |  |  | 					Py_DECREF(f_code); | 
					
						
							|  |  |  | 					Py_DECREF(frame); | 
					
						
							|  |  |  | 					return; | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | 			Py_XDECREF(f_lineno); | 
					
						
							|  |  |  | 			Py_XDECREF(f_code); | 
					
						
							|  |  |  | 			Py_DECREF(frame); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-26 12:51:27 +00:00
										 |  |  | 	PyErr_Clear(); | 
					
						
							|  |  |  | 	printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  | 	PyDebugLine(); | 
					
						
							| 
									
										
										
										
											2009-06-08 20:08:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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;} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 04:11:39 +00:00
										 |  |  | #endif // WITH_PYTHON
 |