On a scene change the SCA_JoystickManager gets destroyed which in turn means all of it's joystick instances are released. Since SCA_PythonJoystick was just using a borrowed reference, this allowed the joystick to be freed. Now the joystick's refcount is incremented so that the SCA_PythonJoystick's joystick reference will survive across scene changes.
		
			
				
	
	
		
			189 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * ***** BEGIN GPL LICENSE BLOCK *****
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software Foundation,
 | |
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | |
|  *
 | |
|  * Contributor(s): Mitchell Stokes.
 | |
|  *
 | |
|  * ***** END GPL LICENSE BLOCK *****
 | |
|  */
 | |
| 
 | |
| /** \file gameengine/GameLogic/SCA_PythonJoystick.cpp
 | |
|  *  \ingroup gamelogic
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include "SCA_PythonJoystick.h"
 | |
| #include "./Joystick/SCA_Joystick.h"
 | |
| #include "SCA_IInputDevice.h"
 | |
| 
 | |
| //#include "GHOST_C-api.h"
 | |
| 
 | |
| /* ------------------------------------------------------------------------- */
 | |
| /* Native functions                                                          */
 | |
| /* ------------------------------------------------------------------------- */
 | |
| 
 | |
| SCA_PythonJoystick::SCA_PythonJoystick(SCA_Joystick* joystick)
 | |
| : PyObjectPlus(),
 | |
| m_joystick(joystick)
 | |
| {
 | |
| #ifdef WITH_PYTHON
 | |
| 	m_event_dict = PyDict_New();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| SCA_PythonJoystick::~SCA_PythonJoystick()
 | |
| {
 | |
| 	// The joystick reference we got in the constructor was a new instance,
 | |
| 	// so we release it here
 | |
| 	m_joystick->ReleaseInstance();
 | |
| 
 | |
| #ifdef WITH_PYTHON
 | |
| 	PyDict_Clear(m_event_dict);
 | |
| 	Py_DECREF(m_event_dict);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #ifdef WITH_PYTHON
 | |
| 
 | |
| /* ------------------------------------------------------------------------- */
 | |
| /* Python functions                                                          */
 | |
| /* ------------------------------------------------------------------------- */
 | |
| PyObject* SCA_PythonJoystick::py_repr(void)
 | |
| {
 | |
| 	return PyUnicode_FromString(m_joystick->GetName());
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Integration hooks ------------------------------------------------------- */
 | |
| PyTypeObject SCA_PythonJoystick::Type = {
 | |
| 	PyVarObject_HEAD_INIT(NULL, 0)
 | |
| 	"SCA_PythonJoystick",
 | |
| 	sizeof(PyObjectPlus_Proxy),
 | |
| 	0,
 | |
| 	py_base_dealloc,
 | |
| 	0,
 | |
| 	0,
 | |
| 	0,
 | |
| 	0,
 | |
| 	py_base_repr,
 | |
| 	0,0,0,0,0,0,0,0,0,
 | |
| 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
 | |
| 	0,0,0,0,0,0,0,
 | |
| 	Methods,
 | |
| 	0,
 | |
| 	0,
 | |
| 	&PyObjectPlus::Type,
 | |
| 	0,0,0,0,0,0,
 | |
| 	py_base_new
 | |
| };
 | |
| 
 | |
| PyMethodDef SCA_PythonJoystick::Methods[] = {
 | |
| 	{NULL,NULL} //Sentinel
 | |
| };
 | |
| 
 | |
| PyAttributeDef SCA_PythonJoystick::Attributes[] = {
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("numButtons", SCA_PythonJoystick, pyattr_get_num_x),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("numHats", SCA_PythonJoystick, pyattr_get_num_x),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("numAxis", SCA_PythonJoystick, pyattr_get_num_x),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("activeButtons", SCA_PythonJoystick, pyattr_get_active_buttons),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_PythonJoystick, pyattr_get_hat_values),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("axisValues", SCA_PythonJoystick, pyattr_get_axis_values),
 | |
| 	KX_PYATTRIBUTE_RO_FUNCTION("name", SCA_PythonJoystick, pyattr_get_name),
 | |
| 	{ NULL }	//Sentinel
 | |
| };
 | |
| 
 | |
| // Use one function for numAxis, numButtons, and numHats
 | |
| PyObject* SCA_PythonJoystick::pyattr_get_num_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 | |
| {
 | |
| 	SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
 | |
| 
 | |
| 	if (strcmp(attrdef->m_name, "numButtons") == 0)
 | |
| 		return PyLong_FromLong(self->m_joystick->GetNumberOfButtons());
 | |
| 	else if (strcmp(attrdef->m_name, "numAxis") == 0)
 | |
| 		return PyLong_FromLong(self->m_joystick->GetNumberOfAxes());
 | |
| 	else if (strcmp(attrdef->m_name, "numHats") == 0)
 | |
| 		return PyLong_FromLong(self->m_joystick->GetNumberOfHats());
 | |
| 
 | |
| 	// If we got here, we have a problem...
 | |
| 	PyErr_SetString(PyExc_AttributeError, "invalid attribute");
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| PyObject* SCA_PythonJoystick::pyattr_get_active_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 | |
| {
 | |
| 	SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
 | |
| 	
 | |
| 	const int button_number = self->m_joystick->GetNumberOfButtons();
 | |
| 
 | |
| 	PyObject *list = PyList_New(0);
 | |
| 	PyObject *value;
 | |
| 
 | |
| 	for (int i=0; i < button_number; i++) {
 | |
| 		if (self->m_joystick->aButtonPressIsPositive(i)) {
 | |
| 			value = PyLong_FromLong(i);
 | |
| 			PyList_Append(list, value);
 | |
| 			Py_DECREF(value);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return list;
 | |
| }
 | |
| 
 | |
| PyObject* SCA_PythonJoystick::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 | |
| {
 | |
| 	SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
 | |
| 	
 | |
| 	int hat_index = self->m_joystick->GetNumberOfHats();
 | |
| 	PyObject *list = PyList_New(hat_index);
 | |
| 	
 | |
| 	while (hat_index--) {
 | |
| 		PyList_SET_ITEM(list, hat_index, PyLong_FromLong(self->m_joystick->GetHat(hat_index)));
 | |
| 	}
 | |
| 	
 | |
| 	return list;
 | |
| }
 | |
| 
 | |
| PyObject* SCA_PythonJoystick::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 | |
| {
 | |
| 	SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
 | |
| 	
 | |
| 	int axis_index = self->m_joystick->GetNumberOfAxes();
 | |
| 	PyObject *list = PyList_New(axis_index);
 | |
| 	int position;
 | |
| 	
 | |
| 	while (axis_index--) {
 | |
| 		position = self->m_joystick->GetAxisPosition(axis_index);
 | |
| 
 | |
| 		// We get back a range from -32768 to 32767, so we use an if here to
 | |
| 		// get a perfect -1.0 to 1.0 mapping. Some oddball system might have an
 | |
| 		// actual min of -32767 for shorts, so we use SHRT_MIN/MAX to be safe.
 | |
| 		if (position < 0)
 | |
| 			PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/((double)-SHRT_MIN)));
 | |
| 		else
 | |
| 			PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/(double)SHRT_MAX));
 | |
| 	}
 | |
| 	
 | |
| 	return list;
 | |
| }
 | |
| 
 | |
| PyObject* SCA_PythonJoystick::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 | |
| {
 | |
| 	SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
 | |
| 
 | |
| 	return PyUnicode_FromString(self->m_joystick->GetName());
 | |
| }
 | |
| #endif
 |