BGE: Adding a Python interface for handling joysticks without needing logic bricks...
[blender.git] / source / gameengine / GameLogic / SCA_PythonJoystick.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Mitchell Stokes.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file gameengine/GameLogic/SCA_PythonJoystick.cpp
24  *  \ingroup gamelogic
25  */
26
27
28 #include "SCA_PythonJoystick.h"
29 #include "./Joystick/SCA_Joystick.h"
30 #include "SCA_IInputDevice.h"
31
32 //#include "GHOST_C-api.h"
33
34 /* ------------------------------------------------------------------------- */
35 /* Native functions                                                          */
36 /* ------------------------------------------------------------------------- */
37
38 SCA_PythonJoystick::SCA_PythonJoystick(SCA_Joystick* joystick)
39 : PyObjectPlus(),
40 m_joystick(joystick)
41 {
42 #ifdef WITH_PYTHON
43         m_event_dict = PyDict_New();
44 #endif
45 }
46
47 SCA_PythonJoystick::~SCA_PythonJoystick()
48 {
49 #ifdef WITH_PYTHON
50         PyDict_Clear(m_event_dict);
51         Py_DECREF(m_event_dict);
52 #endif
53 }
54
55 #ifdef WITH_PYTHON
56
57 /* ------------------------------------------------------------------------- */
58 /* Python functions                                                          */
59 /* ------------------------------------------------------------------------- */
60 PyObject* SCA_PythonJoystick::py_repr(void)
61 {
62         return PyUnicode_FromString(m_joystick->GetName());
63 }
64
65
66 /* Integration hooks ------------------------------------------------------- */
67 PyTypeObject SCA_PythonJoystick::Type = {
68         PyVarObject_HEAD_INIT(NULL, 0)
69         "SCA_PythonJoystick",
70         sizeof(PyObjectPlus_Proxy),
71         0,
72         py_base_dealloc,
73         0,
74         0,
75         0,
76         0,
77         py_base_repr,
78         0,0,0,0,0,0,0,0,0,
79         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
80         0,0,0,0,0,0,0,
81         Methods,
82         0,
83         0,
84         &PyObjectPlus::Type,
85         0,0,0,0,0,0,
86         py_base_new
87 };
88
89 PyMethodDef SCA_PythonJoystick::Methods[] = {
90         {NULL,NULL} //Sentinel
91 };
92
93 PyAttributeDef SCA_PythonJoystick::Attributes[] = {
94         KX_PYATTRIBUTE_RO_FUNCTION("numButtons", SCA_PythonJoystick, pyattr_get_num_x),
95         KX_PYATTRIBUTE_RO_FUNCTION("numHats", SCA_PythonJoystick, pyattr_get_num_x),
96         KX_PYATTRIBUTE_RO_FUNCTION("numAxis", SCA_PythonJoystick, pyattr_get_num_x),
97         KX_PYATTRIBUTE_RO_FUNCTION("activeButtons", SCA_PythonJoystick, pyattr_get_active_buttons),
98         KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_PythonJoystick, pyattr_get_hat_values),
99         KX_PYATTRIBUTE_RO_FUNCTION("axisValues", SCA_PythonJoystick, pyattr_get_axis_values),
100         KX_PYATTRIBUTE_RO_FUNCTION("name", SCA_PythonJoystick, pyattr_get_name),
101         { NULL }        //Sentinel
102 };
103
104 // Use one function for numAxis, numButtons, and numHats
105 PyObject* SCA_PythonJoystick::pyattr_get_num_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
106 {
107         SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
108
109         if (strcmp(attrdef->m_name, "numButtons") == 0)
110                 return PyLong_FromLong(self->m_joystick->GetNumberOfButtons());
111         else if (strcmp(attrdef->m_name, "numAxis") == 0)
112                 return PyLong_FromLong(self->m_joystick->GetNumberOfAxes());
113         else if (strcmp(attrdef->m_name, "numHats") == 0)
114                 return PyLong_FromLong(self->m_joystick->GetNumberOfHats());
115
116         // If we got here, we have a problem...
117         PyErr_SetString(PyExc_AttributeError, "invalid attribute");
118         return NULL;
119 }
120
121 PyObject* SCA_PythonJoystick::pyattr_get_active_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
122 {
123         SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
124         
125         int button_index = self->m_joystick->GetNumberOfButtons();
126
127         PyObject *list = PyList_New(0);
128         PyObject *value;
129
130         for (int i=0; i < self->m_joystick->GetNumberOfButtons(); i++) {
131                 if (self->m_joystick->aButtonPressIsPositive(i)) {
132                         value = PyLong_FromSsize_t(i);
133                         PyList_Append(list, value);
134                         Py_DECREF(value);
135                 }
136         }
137
138         return list;
139 }
140
141 PyObject* SCA_PythonJoystick::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
142 {
143         SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
144         
145         int hat_index = self->m_joystick->GetNumberOfHats();
146         PyObject *list = PyList_New(hat_index);
147         
148         while (hat_index--) {
149                 PyList_SET_ITEM(list, hat_index, PyLong_FromLong(self->m_joystick->GetHat(hat_index)));
150         }
151         
152         return list;
153 }
154
155 PyObject* SCA_PythonJoystick::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
156 {
157         SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
158         
159         int axis_index = self->m_joystick->GetNumberOfAxes();
160         PyObject *list = PyList_New(axis_index);
161         int position;
162         
163         while (axis_index--) {
164                 position = self->m_joystick->GetAxisPosition(axis_index);
165
166                 // We get back a range from -32768 to 32767, so we use an if here to
167                 // get a perfect -1.0 to 1.0 mapping. Some oddball system might have an
168                 // actual min of -32767 for shorts, so we use SHRT_MIN/MAX to be safe.
169                 if (position < 0)
170                         PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/((double)-SHRT_MIN)));
171                 else
172                         PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/(double)SHRT_MAX));
173         }
174         
175         return list;
176 }
177
178 PyObject* SCA_PythonJoystick::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
179 {
180         SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
181
182         return PyUnicode_FromString(self->m_joystick->GetName());
183 }
184 #endif