dce62ad189a50661e100d3cf59b26bd7d0d29e26
[blender.git] / source / gameengine / GameLogic / Joystick / SCA_Joystick.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  * 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): snailrose.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/GameLogic/Joystick/SCA_Joystick.cpp
29  *  \ingroup gamelogic
30  */
31
32 #ifdef WITH_SDL
33 #  include <SDL.h>
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include "SCA_Joystick.h"
40 #include "SCA_JoystickPrivate.h"
41
42 SCA_Joystick::SCA_Joystick(short int index)
43         :
44         m_joyindex(index),
45         m_prec(3200),
46         m_axismax(-1),
47         m_buttonmax(-1),
48         m_hatmax(-1),
49         m_isinit(0),
50         m_istrig_axis(0),
51         m_istrig_button(0),
52         m_istrig_hat(0)
53 {
54         for (int i=0; i < JOYAXIS_MAX; i++)
55                 m_axis_array[i] = 0;
56         
57         for (int i=0; i < JOYHAT_MAX; i++)
58                 m_hat_array[i] = 0;
59         
60 #ifdef WITH_SDL
61         m_private = new PrivateData();
62 #endif
63 }
64
65
66 SCA_Joystick::~SCA_Joystick()
67
68 {
69 #ifdef WITH_SDL
70         delete m_private;
71 #endif
72 }
73
74 SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX];
75 int SCA_Joystick::m_joynum = 0;
76 int SCA_Joystick::m_refCount = 0;
77
78 SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
79 {
80 #ifndef WITH_SDL
81         return NULL;
82 #else  /* WITH_SDL */
83         if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
84                 ECHO("Error-invalid joystick index: " << joyindex);
85                 return NULL;
86         }
87
88         if (m_refCount == 0) 
89         {
90                 int i;
91                 /* The video subsystem is required for joystick input to work. However,
92                  * when GHOST is running under SDL, video is initialized elsewhere.
93                  * Do this once only. */
94 #  ifdef WITH_GHOST_SDL
95                 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1 ) {
96 #  else
97                 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) == -1 ) {
98 #  endif
99                         ECHO("Error-Initializing-SDL: " << SDL_GetError());
100                         return NULL;
101                 }
102                 
103                 m_joynum = SDL_NumJoysticks();
104                 
105                 for (i=0; i<JOYINDEX_MAX; i++) {
106                         m_instance[i] = new SCA_Joystick(i);
107                         m_instance[i]->CreateJoystickDevice();
108                 }
109                 m_refCount = 1;
110         }
111         else
112         {
113                 m_refCount++;
114         }
115         return m_instance[joyindex];
116 #endif /* WITH_SDL */
117 }
118
119 void SCA_Joystick::ReleaseInstance()
120 {
121         if (--m_refCount == 0)
122         {
123 #ifdef WITH_SDL
124                 int i;
125                 for (i=0; i<JOYINDEX_MAX; i++) {
126                         if (m_instance[i]) {
127                                 m_instance[i]->DestroyJoystickDevice();
128                                 delete m_instance[i];
129                         }
130                         m_instance[i] = NULL;
131                 }
132
133                 /* The video subsystem is required for joystick input to work. However,
134                  * when GHOST is running under SDL, video is freed elsewhere.
135                  * Do this once only. */
136 #  ifdef WITH_GHOST_SDL
137                 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
138 #  else
139                 SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO);
140 #  endif
141 #endif /* WITH_SDL */
142         }
143 }
144
145 void SCA_Joystick::cSetPrecision(int val)
146 {
147         m_prec = val;
148 }
149
150
151 bool SCA_Joystick::aAxisPairIsPositive(int axis)
152 {
153         return (pAxisTest(axis) > m_prec) ? true:false;
154 }
155
156 bool SCA_Joystick::aAxisPairDirectionIsPositive(int axis, int dir)
157 {
158
159         int res;
160
161         if (dir==JOYAXIS_UP || dir==JOYAXIS_DOWN)
162                 res = pGetAxis(axis, 1);
163         else /* JOYAXIS_LEFT || JOYAXIS_RIGHT */
164                 res = pGetAxis(axis, 0);
165         
166         if (dir==JOYAXIS_DOWN || dir==JOYAXIS_RIGHT)
167                 return (res > m_prec) ? true : false;
168         else /* JOYAXIS_UP || JOYAXIS_LEFT */
169                 return (res < -m_prec) ? true : false;
170 }
171
172 bool SCA_Joystick::aAxisIsPositive(int axis_single)
173 {
174         return abs(m_axis_array[axis_single]) > m_prec ? true:false;
175 }
176
177 bool SCA_Joystick::aAnyButtonPressIsPositive(void)
178 {
179 #ifdef WITH_SDL
180         /* this is needed for the "all events" option
181          * so we know if there are no buttons pressed */
182         for (int i=0; i<m_buttonmax; i++)
183                 if (SDL_JoystickGetButton(m_private->m_joystick, i))
184                         return true;
185 #endif
186         return false;
187 }
188
189 bool SCA_Joystick::aButtonPressIsPositive(int button)
190 {
191 #ifndef WITH_SDL
192         return false;
193 #else
194         bool result;
195         SDL_JoystickGetButton(m_private->m_joystick, button)? result = true:result = false;
196         return result;
197 #endif
198 }
199
200
201 bool SCA_Joystick::aButtonReleaseIsPositive(int button)
202 {
203 #ifndef WITH_SDL
204         return false;
205 #else
206         bool result;
207         SDL_JoystickGetButton(m_private->m_joystick, button)? result = false : result = true;
208         return result;
209 #endif
210 }
211
212
213 bool SCA_Joystick::aHatIsPositive(int hatnum, int dir)
214 {
215         return (GetHat(hatnum)==dir) ? true : false;
216 }
217
218 int SCA_Joystick::GetNumberOfAxes()
219 {
220         return m_axismax;
221 }
222
223
224 int SCA_Joystick::GetNumberOfButtons()
225 {
226         return m_buttonmax;
227 }
228
229
230 int SCA_Joystick::GetNumberOfHats()
231 {
232         return m_hatmax;
233 }
234
235 bool SCA_Joystick::CreateJoystickDevice(void)
236 {
237 #ifndef WITH_SDL
238         m_isinit = true;
239         m_axismax = m_buttonmax = m_hatmax = 0;
240         return false;
241 #else /* WITH_SDL */
242         if (m_isinit == false) {
243                 if (m_joyindex>=m_joynum) {
244                         /* don't print a message, because this is done anyway */
245                         //ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
246                         
247                         /* Need this so python args can return empty lists */
248                         m_axismax = m_buttonmax = m_hatmax = 0;
249                         return false;
250                 }
251
252                 m_private->m_joystick = SDL_JoystickOpen(m_joyindex);
253                 SDL_JoystickEventState(SDL_ENABLE);
254                 m_isinit = true;
255                 
256                 ECHO("Joystick " << m_joyindex << " initialized");
257                 
258                 /* must run after being initialized */
259                 m_axismax     = SDL_JoystickNumAxes(m_private->m_joystick);
260                 m_buttonmax   = SDL_JoystickNumButtons(m_private->m_joystick);
261                 m_hatmax      = SDL_JoystickNumHats(m_private->m_joystick);
262
263                 if      (m_axismax > JOYAXIS_MAX) m_axismax = JOYAXIS_MAX;  /* very unlikely */
264                 else if (m_axismax < 0)           m_axismax = 0;
265                 
266                 if      (m_hatmax > JOYHAT_MAX) m_hatmax = JOYHAT_MAX;  /* very unlikely */
267                 else if (m_hatmax < 0)          m_hatmax = 0;
268                 
269                 if (m_buttonmax < 0) m_buttonmax = 0;
270                 
271         }
272         return true;
273 #endif /* WITH_SDL */
274 }
275
276
277 void SCA_Joystick::DestroyJoystickDevice(void)
278 {
279 #ifdef WITH_SDL
280         if (m_isinit) {
281                 if (SDL_JoystickOpened(m_joyindex)) {
282                         ECHO("Closing-joystick " << m_joyindex);
283                         SDL_JoystickClose(m_private->m_joystick);
284                 }
285                 m_isinit = false;
286         }
287 #endif /* WITH_SDL */
288 }
289
290 int SCA_Joystick::Connected(void)
291 {
292 #ifdef WITH_SDL
293         if (m_isinit && SDL_JoystickOpened(m_joyindex))
294                 return 1;
295 #endif
296         return 0;
297 }
298
299 int SCA_Joystick::pGetAxis(int axisnum, int udlr)
300 {
301 #ifdef WITH_SDL
302         return m_axis_array[(axisnum*2)+udlr];
303 #endif
304         return 0;
305 }
306
307 int SCA_Joystick::pAxisTest(int axisnum)
308 {
309 #ifdef WITH_SDL
310         /* Use ints instead of shorts here to avoid problems when we get -32768.
311          * When we take the negative of that later, we should get 32768, which is greater
312          * than what a short can hold. In other words, abs(MIN_SHORT) > MAX_SHRT. */
313         int i1 = m_axis_array[(axisnum * 2)];
314         int i2 = m_axis_array[(axisnum * 2) + 1];
315         
316         /* long winded way to do:
317          * return max_ff(absf(i1), absf(i2))
318          * ...avoid abs from math.h */
319         if (i1 < 0) i1 = -i1;
320         if (i2 < 0) i2 = -i2;
321         if (i1 <i2) return i2;
322         else        return i1;
323 #else /* WITH_SDL */
324         return 0;
325 #endif /* WITH_SDL */
326 }
327
328 const char *SCA_Joystick::GetName()
329 {
330 #ifdef WITH_SDL
331         return SDL_JoystickName(m_joyindex);
332 #else /* WITH_SDL */
333         return "";
334 #endif /* WITH_SDL */
335 }