/* * ***** 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. * * 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): snailrose. * * ***** END GPL LICENSE BLOCK ***** */ /** \file gameengine/GameLogic/Joystick/SCA_Joystick.cpp * \ingroup gamelogic */ #ifdef WITH_SDL # include #endif #include #include #include "SCA_Joystick.h" #include "SCA_JoystickPrivate.h" #include "BLI_path_util.h" SCA_Joystick::SCA_Joystick(short int index) : m_joyindex(index), m_prec(3200), m_axismax(-1), m_buttonmax(-1), m_hatmax(-1), m_isinit(0), m_istrig_axis(0), m_istrig_button(0), m_istrig_hat(0) { for (int i=0; i < JOYAXIS_MAX; i++) m_axis_array[i] = 0; for (int i=0; i < JOYHAT_MAX; i++) m_hat_array[i] = 0; #ifdef WITH_SDL m_private = new PrivateData(); #endif } SCA_Joystick::~SCA_Joystick() { #ifdef WITH_SDL delete m_private; #endif } SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; int SCA_Joystick::m_joynum = 0; int SCA_Joystick::m_refCount = 0; SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) { #ifndef WITH_SDL return NULL; #else /* WITH_SDL */ if (joyindex < 0 || joyindex >= JOYINDEX_MAX) { JOYSTICK_ECHO("Error-invalid joystick index: " << joyindex); return NULL; } if (m_refCount == 0) { int i; /* The video subsystem is required for joystick input to work. However, * when GHOST is running under SDL, video is initialized elsewhere. We * also need to set the videodriver to dummy, and do it here to avoid * interfering with addons that may use SDL too. * * We also init SDL once only. */ # ifdef WITH_GHOST_SDL int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 ); # else /* set and restore environment variable */ char *videodriver = getenv("SDL_VIDEODRIVER"); BLI_setenv("SDL_VIDEODRIVER", "dummy"); int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != -1 ); BLI_setenv("SDL_VIDEODRIVER", videodriver); # endif if (!success) { JOYSTICK_ECHO("Error-Initializing-SDL: " << SDL_GetError()); return NULL; } m_joynum = SDL_NumJoysticks(); for (i=0; iCreateJoystickDevice(); } m_refCount = 1; } else { m_refCount++; } return m_instance[joyindex]; #endif /* WITH_SDL */ } void SCA_Joystick::ReleaseInstance() { if (--m_refCount == 0) { #ifdef WITH_SDL int i; for (i=0; iDestroyJoystickDevice(); delete m_instance[i]; } m_instance[i] = NULL; } /* The video subsystem is required for joystick input to work. However, * when GHOST is running under SDL, video is freed elsewhere. * Do this once only. */ # ifdef WITH_GHOST_SDL SDL_QuitSubSystem(SDL_INIT_JOYSTICK); # else SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO); # endif #endif /* WITH_SDL */ } } void SCA_Joystick::cSetPrecision(int val) { m_prec = val; } bool SCA_Joystick::aAxisPairIsPositive(int axis) { return (pAxisTest(axis) > m_prec) ? true:false; } bool SCA_Joystick::aAxisPairDirectionIsPositive(int axis, int dir) { int res; if (dir==JOYAXIS_UP || dir==JOYAXIS_DOWN) res = pGetAxis(axis, 1); else /* JOYAXIS_LEFT || JOYAXIS_RIGHT */ res = pGetAxis(axis, 0); if (dir==JOYAXIS_DOWN || dir==JOYAXIS_RIGHT) return (res > m_prec) ? true : false; else /* JOYAXIS_UP || JOYAXIS_LEFT */ return (res < -m_prec) ? true : false; } bool SCA_Joystick::aAxisIsPositive(int axis_single) { return abs(m_axis_array[axis_single]) > m_prec ? true:false; } bool SCA_Joystick::aAnyButtonPressIsPositive(void) { #ifdef WITH_SDL /* this is needed for the "all events" option * so we know if there are no buttons pressed */ for (int i=0; im_joystick, i)) return true; #endif return false; } bool SCA_Joystick::aButtonPressIsPositive(int button) { #ifndef WITH_SDL return false; #else bool result; SDL_JoystickGetButton(m_private->m_joystick, button)? result = true:result = false; return result; #endif } bool SCA_Joystick::aButtonReleaseIsPositive(int button) { #ifndef WITH_SDL return false; #else bool result; SDL_JoystickGetButton(m_private->m_joystick, button)? result = false : result = true; return result; #endif } bool SCA_Joystick::aHatIsPositive(int hatnum, int dir) { return (GetHat(hatnum)==dir) ? true : false; } int SCA_Joystick::GetNumberOfAxes() { return m_axismax; } int SCA_Joystick::GetNumberOfButtons() { return m_buttonmax; } int SCA_Joystick::GetNumberOfHats() { return m_hatmax; } bool SCA_Joystick::CreateJoystickDevice(void) { #ifndef WITH_SDL m_isinit = true; m_axismax = m_buttonmax = m_hatmax = 0; return false; #else /* WITH_SDL */ if (m_isinit == false) { if (m_joyindex>=m_joynum) { /* don't print a message, because this is done anyway */ //JOYSTICK_ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); /* Need this so python args can return empty lists */ m_axismax = m_buttonmax = m_hatmax = 0; return false; } m_private->m_joystick = SDL_JoystickOpen(m_joyindex); SDL_JoystickEventState(SDL_ENABLE); m_isinit = true; JOYSTICK_ECHO("Joystick " << m_joyindex << " initialized"); /* must run after being initialized */ m_axismax = SDL_JoystickNumAxes(m_private->m_joystick); m_buttonmax = SDL_JoystickNumButtons(m_private->m_joystick); m_hatmax = SDL_JoystickNumHats(m_private->m_joystick); if (m_axismax > JOYAXIS_MAX) m_axismax = JOYAXIS_MAX; /* very unlikely */ else if (m_axismax < 0) m_axismax = 0; if (m_hatmax > JOYHAT_MAX) m_hatmax = JOYHAT_MAX; /* very unlikely */ else if (m_hatmax < 0) m_hatmax = 0; if (m_buttonmax < 0) m_buttonmax = 0; } return true; #endif /* WITH_SDL */ } void SCA_Joystick::DestroyJoystickDevice(void) { #ifdef WITH_SDL if (m_isinit) { #if SDL_VERSION_ATLEAST(2, 0, 0) if (SDL_JoystickGetAttached(m_private->m_joystick)) { #else if (SDL_JoystickOpened(m_joyindex)) { #endif JOYSTICK_ECHO("Closing-joystick " << m_joyindex); SDL_JoystickClose(m_private->m_joystick); } m_isinit = false; } #endif /* WITH_SDL */ } int SCA_Joystick::Connected(void) { #ifdef WITH_SDL if (m_isinit #if SDL_VERSION_ATLEAST(2, 0, 0) && SDL_JoystickGetAttached(m_private->m_joystick)) #else && SDL_JoystickOpened(m_joyindex)) #endif return 1; #endif return 0; } int SCA_Joystick::pGetAxis(int axisnum, int udlr) { #ifdef WITH_SDL return m_axis_array[(axisnum*2)+udlr]; #endif return 0; } int SCA_Joystick::pAxisTest(int axisnum) { #ifdef WITH_SDL /* Use ints instead of shorts here to avoid problems when we get -32768. * When we take the negative of that later, we should get 32768, which is greater * than what a short can hold. In other words, abs(MIN_SHORT) > MAX_SHRT. */ int i1 = m_axis_array[(axisnum * 2)]; int i2 = m_axis_array[(axisnum * 2) + 1]; /* long winded way to do: * return max_ff(absf(i1), absf(i2)) * ...avoid abs from math.h */ if (i1 < 0) i1 = -i1; if (i2 < 0) i2 = -i2; if (i1 m_joystick); #else return SDL_JoystickName(m_joyindex); #endif #else /* WITH_SDL */ return ""; #endif /* WITH_SDL */ }