Merge with -r 22620:23107.
[blender.git] / source / gameengine / GameLogic / SCA_JoystickSensor.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27 #include "SCA_JoystickManager.h"
28 #include "SCA_JoystickSensor.h"
29
30 #include "SCA_EventManager.h"
31 #include "SCA_LogicManager.h"
32
33 #include "PyObjectPlus.h"
34
35 #include <iostream>
36
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42
43 SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
44                                                                            SCA_IObject* gameobj,
45                                                                            short int joyindex,
46                                                                            short int joymode,
47                                                                            int axis, int axisf,int prec,
48                                                                            int button,
49                                                                            int hat, int hatf, bool allevents)
50                                                                            :SCA_ISensor(gameobj,eventmgr),
51                                                                            m_axis(axis),
52                                                                            m_axisf(axisf),
53                                                                            m_button(button),
54                                                                            m_hat(hat),
55                                                                            m_hatf(hatf),
56                                                                            m_precision(prec),
57                                                                            m_joymode(joymode),
58                                                                            m_joyindex(joyindex),
59                                                                            m_bAllEvents(allevents)
60 {       
61 /*
62 std::cout << " axis "           << m_axis               << std::endl;
63 std::cout << " axis flag "      << m_axisf              << std::endl;
64 std::cout << " precision "      << m_precision  << std::endl;
65 std::cout << " button "         << m_button     << std::endl;
66 std::cout << " hat "            << m_hat                << std::endl;
67 std::cout << " hat flag "       << m_hatf               << std::endl;
68 */
69         Init();
70 }
71
72 void SCA_JoystickSensor::Init()
73 {
74         m_istrig=(m_invert)?1:0;
75         m_istrig_prev=0;
76         m_reset = true;
77 }
78
79 SCA_JoystickSensor::~SCA_JoystickSensor()
80 {
81 }
82
83
84 CValue* SCA_JoystickSensor::GetReplica()
85 {
86         SCA_JoystickSensor* replica = new SCA_JoystickSensor(*this);
87         // this will copy properties and so on...
88         replica->ProcessReplica();
89         replica->Init();
90         return replica;
91 }
92
93
94 bool SCA_JoystickSensor::IsPositiveTrigger()
95
96         bool result =   m_istrig;
97         if (m_invert)
98                 result = !result;
99         return result;
100 }
101
102
103 bool SCA_JoystickSensor::Evaluate()
104 {
105         SCA_Joystick *js = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex);
106         bool result = false;
107         bool reset = m_reset && m_level;
108         
109         if(js==NULL) /* no joystick - dont do anything */
110                 return false;
111         
112         m_reset = false;
113         switch(m_joymode)
114         {
115         case KX_JOYSENSORMODE_AXIS:
116                 {
117                 /* what is what!
118                         m_axisf == JOYAXIS_RIGHT, JOYAXIS_UP, JOYAXIS_DOWN, JOYAXIS_LEFT
119                         m_axisf == 1 == up
120                         m_axisf == 2 == left
121                         m_axisf == 3 == down
122                         
123                         numberof== m_axis (1-4), range is half of JOYAXIS_MAX since 
124                                 it assumes the axis joysticks are axis parirs (0,1), (2,3), etc
125                                 also note that this starts at 1 where functions its used
126                                 with expect a zero index.
127                         */
128                         
129                         if (!js->IsTrigAxis() && !reset) /* No events from SDL? - dont bother */
130                                 return false;
131                         
132                         js->cSetPrecision(m_precision);
133                         if (m_bAllEvents) {
134                                 if(js->aAxisPairIsPositive(m_axis-1)){ /* use zero based axis index internally */
135                                         m_istrig = 1;
136                                         result = true;
137                                 }else{
138                                         if(m_istrig){
139                                                 m_istrig = 0;
140                                                 result = true;
141                                         }
142                                 }
143                         }
144                         else {
145                                 if(js->aAxisPairDirectionIsPositive(m_axis-1, m_axisf)){ /* use zero based axis index internally */
146                                         m_istrig = 1;
147                                         result = true;
148                                 }else{
149                                         if(m_istrig){
150                                                 m_istrig = 0;
151                                                 result = true;
152                                         }
153                                 }
154                         }
155                         break;
156                 }
157         case KX_JOYSENSORMODE_AXIS_SINGLE:
158                 {
159                         /* Like KX_JOYSENSORMODE_AXIS but dont pair up axis */
160                         if (!js->IsTrigAxis() && !reset) /* No events from SDL? - dont bother */
161                                 return false;
162                         
163                         /* No need for 'm_bAllEvents' check here since were only checking 1 axis */
164                         js->cSetPrecision(m_precision);
165                         if(js->aAxisIsPositive(m_axis-1)){ /* use zero based axis index internally */
166                                 m_istrig = 1;
167                                 result = true;
168                         }else{
169                                 if(m_istrig){
170                                         m_istrig = 0;
171                                         result = true;
172                                 }
173                         }
174                         break;
175                 }
176                 
177         case KX_JOYSENSORMODE_BUTTON:
178                 {
179                 /* what is what!
180                         m_button = the actual button in question
181                         */
182                         if (!js->IsTrigButton() && !reset) /* No events from SDL? - dont bother */
183                                 return false;
184                         
185                         if(( m_bAllEvents && js->aAnyButtonPressIsPositive()) || (!m_bAllEvents && js->aButtonPressIsPositive(m_button))) {
186                                 m_istrig = 1;
187                                 result = true;
188                         }else {
189                                 if(m_istrig){
190                                         m_istrig = 0;
191                                         result = true;
192                                 }
193                         }
194                         break;
195                 }
196         case KX_JOYSENSORMODE_HAT:
197                 {
198                 /* what is what!
199                         numberof = m_hat  -- max 4
200                         direction= m_hatf -- max 12
201                         */
202                         
203                         if (!js->IsTrigHat() && !reset) /* No events from SDL? - dont bother */
204                                 return false;
205                         
206                         if((m_bAllEvents && js->GetHat(m_hat-1)) || js->aHatIsPositive(m_hat-1, m_hatf)) {
207                                 m_istrig = 1;
208                                 result = true;
209                         }else{
210                                 if(m_istrig){
211                                         m_istrig = 0;
212                                         result = true;
213                                 }
214                         }
215                         break;
216                 }
217                 /* test for ball anyone ?*/
218         default:
219                 printf("Error invalid switch statement\n");
220                 break;
221         }
222         
223         /* if not all events are enabled, only send a positive pulse when 
224          * the button state changes */
225         if (!m_bAllEvents) {
226                 if (m_istrig_prev == m_istrig) {
227                         result = false;
228                 } else {
229                         m_istrig_prev = m_istrig;
230                 }
231         }
232         
233         if (reset)
234                 result = true;
235         
236         return result;
237 }
238
239
240 bool SCA_JoystickSensor::isValid(SCA_JoystickSensor::KX_JOYSENSORMODE m)
241 {
242         bool res = false;
243         res = ((m > KX_JOYSENSORMODE_NODEF) && (m < KX_JOYSENSORMODE_MAX));
244         return res;
245 }
246
247
248 /* ------------------------------------------------------------------------- */
249 /* Python functions                                                                                                              */
250 /* ------------------------------------------------------------------------- */
251
252 /* Integration hooks ------------------------------------------------------- */
253 PyTypeObject SCA_JoystickSensor::Type = {
254         PyVarObject_HEAD_INIT(NULL, 0)
255         "SCA_JoystickSensor",
256         sizeof(PyObjectPlus_Proxy),
257         0,
258         py_base_dealloc,
259         0,
260         0,
261         0,
262         0,
263         py_base_repr,
264         0,0,0,0,0,0,0,0,0,
265         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
266         0,0,0,0,0,0,0,
267         Methods,
268         0,
269         0,
270         &SCA_ISensor::Type,
271         0,0,0,0,0,0,
272         py_base_new
273 };
274
275 PyMethodDef SCA_JoystickSensor::Methods[] = {
276         {"getButtonActiveList",(PyCFunction) SCA_JoystickSensor::sPyGetButtonActiveList,        METH_NOARGS,(const char *)GetButtonActiveList_doc},
277         {"getButtonStatus",(PyCFunction) SCA_JoystickSensor::sPyGetButtonStatus,        METH_VARARGS,(const char *)GetButtonStatus_doc},
278         {NULL,NULL} //Sentinel
279 };
280
281 PyAttributeDef SCA_JoystickSensor::Attributes[] = {
282         KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,true,SCA_JoystickSensor,m_joyindex),
283         KX_PYATTRIBUTE_INT_RW("threshold",0,32768,true,SCA_JoystickSensor,m_precision),
284         KX_PYATTRIBUTE_INT_RW("button",0,100,false,SCA_JoystickSensor,m_button),
285         KX_PYATTRIBUTE_INT_LIST_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis),
286         KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat),
287         KX_PYATTRIBUTE_RO_FUNCTION("axisValues",        SCA_JoystickSensor, pyattr_get_axis_values),
288         KX_PYATTRIBUTE_RO_FUNCTION("axisSingle", SCA_JoystickSensor, pyattr_get_axis_single),
289         KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_JoystickSensor, pyattr_get_hat_values),
290         KX_PYATTRIBUTE_RO_FUNCTION("hatSingle", SCA_JoystickSensor, pyattr_get_hat_single),
291         KX_PYATTRIBUTE_RO_FUNCTION("numAxis",           SCA_JoystickSensor, pyattr_get_num_axis),
292         KX_PYATTRIBUTE_RO_FUNCTION("numButtons",        SCA_JoystickSensor, pyattr_get_num_buttons),
293         KX_PYATTRIBUTE_RO_FUNCTION("numHats",           SCA_JoystickSensor, pyattr_get_num_hats),
294         KX_PYATTRIBUTE_RO_FUNCTION("connected",         SCA_JoystickSensor, pyattr_get_connected),
295         //KX_PYATTRIBUTE_TODO("events"),
296         { NULL }        //Sentinel
297 };
298
299 /* get button active list  -------------------------------------------------- */
300 const char SCA_JoystickSensor::GetButtonActiveList_doc[] = 
301 "getButtonActiveList\n"
302 "\tReturns a list containing the indicies of the button currently pressed.\n";
303 PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) {
304         SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex);
305         PyObject *ls = PyList_New(0);
306         PyObject *value;
307         int i;
308         
309         if(joy) {
310                 for (i=0; i < joy->GetNumberOfButtons(); i++) {
311                         if (joy->aButtonPressIsPositive(i)) {
312                                 value = PyLong_FromSsize_t(i);
313                                 PyList_Append(ls, value);
314                                 Py_DECREF(value);
315                         }
316                 }
317         }
318         return ls;
319 }
320
321 /* get button status  -------------------------------------------------- */
322 const char SCA_JoystickSensor::GetButtonStatus_doc[] = 
323 "getButtonStatus(buttonIndex)\n"
324 "\tReturns a bool of the current pressed state of the specified button.\n";
325 PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args ) {
326         SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex);
327         int index;
328         
329         if(!PyArg_ParseTuple(args, "i:getButtonStatus", &index)){
330                 return NULL;
331         }
332         if(joy && index >= 0 && index < joy->GetNumberOfButtons()) {
333                 return PyBool_FromLong(joy->aButtonPressIsPositive(index) ? 1 : 0);
334         }
335         return PyBool_FromLong(0);
336 }
337
338 PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
339 {
340         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
341         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
342         
343         int axis_index= joy->GetNumberOfAxes();
344         PyObject *list= PyList_New(axis_index);
345         
346         while(axis_index--) {
347                 PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index)));
348         }
349         
350         return list;
351 }
352
353 PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
354 {
355         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
356         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
357         
358         if(self->m_joymode != KX_JOYSENSORMODE_AXIS_SINGLE) {
359                 PyErr_SetString(PyExc_TypeError, "val = sensor.axisSingle: Joystick Sensor, not 'Single Axis' type");
360                 return NULL;
361         }
362         
363         return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1));
364 }
365
366 PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
367 {
368         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
369         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
370         
371         int hat_index= joy->GetNumberOfHats();
372         PyObject *list= PyList_New(hat_index);
373         
374         while(hat_index--) {
375                 PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index)));
376         }
377         
378         return list;
379 }
380
381 PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
382 {
383         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
384         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
385         
386         return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1));
387 }
388
389 PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
390 {
391         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
392         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
393         return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 );
394 }
395
396 PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
397 {
398         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
399         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
400         return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 );
401 }
402
403 PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
404 {
405         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
406         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
407         return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 );
408 }
409
410 PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
411 {
412         SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v);
413         SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex);
414         return PyBool_FromLong( joy ? joy->Connected() : 0 );
415 }