Refactored wiimote handling, splitting into two separate files.
Also added non-threading support (while it is too slow/too high latency it's useful for debugging). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12781 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
e45f728008
commit
7ac899ade7
@ -76,6 +76,7 @@ src/input/binding.cpp
|
||||
src/input/device_manager.cpp
|
||||
src/input/input_device.cpp
|
||||
src/input/input_manager.cpp
|
||||
src/input/wiimote.cpp
|
||||
src/input/wiimote_manager.cpp
|
||||
src/io/file_manager.cpp
|
||||
src/io/xml_node.cpp
|
||||
@ -94,8 +95,8 @@ src/items/projectile_manager.cpp
|
||||
src/items/rubber_ball.cpp
|
||||
src/items/rubber_band.cpp
|
||||
src/items/swatter.cpp
|
||||
src/karts/abstract_kart_animation.cpp
|
||||
src/karts/abstract_kart.cpp
|
||||
src/karts/abstract_kart_animation.cpp
|
||||
src/karts/cannon_animation.cpp
|
||||
src/karts/controller/ai_base_controller.cpp
|
||||
src/karts/controller/ai_properties.cpp
|
||||
@ -185,13 +186,13 @@ src/states_screens/kart_selection.cpp
|
||||
src/states_screens/main_menu_screen.cpp
|
||||
src/states_screens/minimal_race_gui.cpp
|
||||
src/states_screens/options_screen_audio.cpp
|
||||
src/states_screens/options_screen_input2.cpp
|
||||
src/states_screens/options_screen_input.cpp
|
||||
src/states_screens/options_screen_input2.cpp
|
||||
src/states_screens/options_screen_players.cpp
|
||||
src/states_screens/options_screen_ui.cpp
|
||||
src/states_screens/options_screen_video.cpp
|
||||
src/states_screens/race_gui_base.cpp
|
||||
src/states_screens/race_gui.cpp
|
||||
src/states_screens/race_gui_base.cpp
|
||||
src/states_screens/race_gui_overworld.cpp
|
||||
src/states_screens/race_result_gui.cpp
|
||||
src/states_screens/race_setup_screen.cpp
|
||||
@ -251,8 +252,8 @@ src/animations/animation_base.hpp
|
||||
src/animations/ipo.hpp
|
||||
src/animations/three_d_animation.hpp
|
||||
src/audio/dummy_sfx.hpp
|
||||
src/audio/music_dummy.hpp
|
||||
src/audio/music.hpp
|
||||
src/audio/music_dummy.hpp
|
||||
src/audio/music_information.hpp
|
||||
src/audio/music_manager.hpp
|
||||
src/audio/music_ogg.hpp
|
||||
@ -260,8 +261,8 @@ src/audio/sfx_base.hpp
|
||||
src/audio/sfx_buffer.hpp
|
||||
src/audio/sfx_manager.hpp
|
||||
src/audio/sfx_openal.hpp
|
||||
src/challenges/challenge_data.hpp
|
||||
src/challenges/challenge.hpp
|
||||
src/challenges/challenge_data.hpp
|
||||
src/challenges/game_slot.hpp
|
||||
src/challenges/unlock_manager.hpp
|
||||
src/config/device_config.hpp
|
||||
@ -302,11 +303,11 @@ src/guiengine/scalable_font.hpp
|
||||
src/guiengine/screen.hpp
|
||||
src/guiengine/skin.hpp
|
||||
src/guiengine/widget.hpp
|
||||
src/guiengine/widgets.hpp
|
||||
src/guiengine/widgets/bubble_widget.hpp
|
||||
src/guiengine/widgets/button_widget.hpp
|
||||
src/guiengine/widgets/check_box_widget.hpp
|
||||
src/guiengine/widgets/dynamic_ribbon_widget.hpp
|
||||
src/guiengine/widgets.hpp
|
||||
src/guiengine/widgets/icon_button_widget.hpp
|
||||
src/guiengine/widgets/label_widget.hpp
|
||||
src/guiengine/widgets/list_widget.hpp
|
||||
@ -317,9 +318,10 @@ src/guiengine/widgets/spinner_widget.hpp
|
||||
src/guiengine/widgets/text_box_widget.hpp
|
||||
src/input/binding.hpp
|
||||
src/input/device_manager.hpp
|
||||
src/input/input_device.hpp
|
||||
src/input/input.hpp
|
||||
src/input/input_device.hpp
|
||||
src/input/input_manager.hpp
|
||||
src/input/wiimote.hpp
|
||||
src/input/wiimote_manager.hpp
|
||||
src/io/file_manager.hpp
|
||||
src/io/xml_node.hpp
|
||||
@ -339,8 +341,8 @@ src/items/projectile_manager.hpp
|
||||
src/items/rubber_ball.hpp
|
||||
src/items/rubber_band.hpp
|
||||
src/items/swatter.hpp
|
||||
src/karts/abstract_kart_animation.hpp
|
||||
src/karts/abstract_kart.hpp
|
||||
src/karts/abstract_kart_animation.hpp
|
||||
src/karts/cannon_animation.hpp
|
||||
src/karts/controller/ai_base_controller.hpp
|
||||
src/karts/controller/ai_properties.hpp
|
||||
@ -351,8 +353,8 @@ src/karts/controller/player_controller.hpp
|
||||
src/karts/controller/skidding_ai.hpp
|
||||
src/karts/explosion_animation.hpp
|
||||
src/karts/ghost_kart.hpp
|
||||
src/karts/kart_gfx.hpp
|
||||
src/karts/kart.hpp
|
||||
src/karts/kart_gfx.hpp
|
||||
src/karts/kart_model.hpp
|
||||
src/karts/kart_properties.hpp
|
||||
src/karts/kart_properties_manager.hpp
|
||||
@ -443,13 +445,13 @@ src/states_screens/kart_selection.hpp
|
||||
src/states_screens/main_menu_screen.hpp
|
||||
src/states_screens/minimal_race_gui.hpp
|
||||
src/states_screens/options_screen_audio.hpp
|
||||
src/states_screens/options_screen_input2.hpp
|
||||
src/states_screens/options_screen_input.hpp
|
||||
src/states_screens/options_screen_input2.hpp
|
||||
src/states_screens/options_screen_players.hpp
|
||||
src/states_screens/options_screen_ui.hpp
|
||||
src/states_screens/options_screen_video.hpp
|
||||
src/states_screens/race_gui_base.hpp
|
||||
src/states_screens/race_gui.hpp
|
||||
src/states_screens/race_gui_base.hpp
|
||||
src/states_screens/race_gui_overworld.hpp
|
||||
src/states_screens/race_result_gui.hpp
|
||||
src/states_screens/race_setup_screen.hpp
|
||||
@ -479,8 +481,8 @@ src/tracks/check_sphere.hpp
|
||||
src/tracks/check_structure.hpp
|
||||
src/tracks/graph_node.hpp
|
||||
src/tracks/lod_node_loader.hpp
|
||||
src/tracks/quad_graph.hpp
|
||||
src/tracks/quad.hpp
|
||||
src/tracks/quad_graph.hpp
|
||||
src/tracks/quad_set.hpp
|
||||
src/tracks/terrain_info.hpp
|
||||
src/tracks/track.hpp
|
||||
|
@ -310,14 +310,15 @@ void GamepadConfig::setDefaultBinds ()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GamepadConfig::GamepadConfig ( const std::string name,
|
||||
GamepadConfig::GamepadConfig ( const std::string &name,
|
||||
const int axis_count,
|
||||
const int btnCount ) : DeviceConfig( DEVICE_CONFIG_TYPE_GAMEPAD )
|
||||
const int button_count )
|
||||
: DeviceConfig( DEVICE_CONFIG_TYPE_GAMEPAD )
|
||||
{
|
||||
m_name = name;
|
||||
m_axis_count = axis_count;
|
||||
m_button_count = btnCount;
|
||||
m_plugged = 0;
|
||||
m_name = name;
|
||||
m_axis_count = axis_count;
|
||||
m_button_count = button_count;
|
||||
m_plugged = 0;
|
||||
setDefaultBinds();
|
||||
}
|
||||
|
||||
|
@ -159,21 +159,28 @@ class GamepadConfig : public DeviceConfig
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
/** Number of axis this device has. */
|
||||
int m_axis_count;
|
||||
|
||||
/** Number of buttons this device has. */
|
||||
int m_button_count;
|
||||
|
||||
public:
|
||||
|
||||
irr::core::stringw toString ();
|
||||
int getAxisCount() const { return m_axis_count; };
|
||||
int getButtonCount() const { return m_button_count; };
|
||||
|
||||
void serialize (std::ofstream& stream);
|
||||
void setDefaultBinds ();
|
||||
GamepadConfig (irr::io::IrrXMLReader* xml);
|
||||
GamepadConfig (const std::string name,
|
||||
const int axis_count,
|
||||
const int btnCount);
|
||||
GamepadConfig (const std::string &name,
|
||||
const int axis_count=0,
|
||||
const int button_ount=0);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of buttons this device has. */
|
||||
void setNumberOfButtons(int count) { m_button_count = count; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of axis this device has. */
|
||||
void setNumberOfAxis(int count) { m_axis_count = count; }
|
||||
// ~GamepadConfig();
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -864,6 +864,9 @@
|
||||
<ClCompile Include="..\..\tracks\track_object_presentation.cpp">
|
||||
<Filter>Source Files\tracks</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\input\wiimote.cpp">
|
||||
<Filter>Source Files\input</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\main_loop.hpp">
|
||||
@ -1655,5 +1658,8 @@
|
||||
<ClInclude Include="..\..\tracks\track_object_presentation.hpp">
|
||||
<Filter>Header Files\tracks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\input\wiimote.hpp">
|
||||
<Filter>Header Files\input</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
File diff suppressed because it is too large
Load Diff
@ -864,6 +864,9 @@
|
||||
<ClCompile Include="..\..\tracks\track_object_presentation.cpp">
|
||||
<Filter>Source Files\tracks</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\input\wiimote.cpp">
|
||||
<Filter>Source Files\input</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\main_loop.hpp">
|
||||
@ -1655,5 +1658,8 @@
|
||||
<ClInclude Include="..\..\tracks\track_object_presentation.hpp">
|
||||
<Filter>Header Files\tracks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\input\wiimote.hpp">
|
||||
<Filter>Header Files\input</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
File diff suppressed because it is too large
Load Diff
@ -49,7 +49,6 @@ bool DeviceManager::initialize()
|
||||
GamePadDevice *gamepadDevice = NULL;
|
||||
m_map_fire_to_select = false;
|
||||
bool created = false;
|
||||
int numGamepads;
|
||||
|
||||
|
||||
// Shutdown in case the device manager is being re-initialized
|
||||
@ -83,19 +82,19 @@ bool DeviceManager::initialize()
|
||||
printf("Initializing gamepad support.\n");
|
||||
|
||||
irr_driver->getDevice()->activateJoysticks(m_irrlicht_gamepads);
|
||||
numGamepads = m_irrlicht_gamepads.size();
|
||||
int num_gamepads = m_irrlicht_gamepads.size();
|
||||
if(UserConfigParams::logMisc())
|
||||
{
|
||||
printf("Irrlicht reports %d gamepads are attached to the system.\n",
|
||||
numGamepads);
|
||||
num_gamepads);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create GamePadDevice for each physical gamepad and find a GamepadConfig to match
|
||||
for (int id = 0; id < numGamepads; id++)
|
||||
for (int id = 0; id < num_gamepads; id++)
|
||||
{
|
||||
core::stringc name = m_irrlicht_gamepads[id].Name.c_str();
|
||||
core::stringc name = m_irrlicht_gamepads[id].Name;
|
||||
|
||||
// Some linux systems report a disk accelerometer as a gamepad, skip that
|
||||
if (name.find("LIS3LV02DL") != -1) continue;
|
||||
@ -103,9 +102,9 @@ bool DeviceManager::initialize()
|
||||
#ifdef WIN32
|
||||
// On Windows, unless we use DirectInput, all gamepads are given the
|
||||
// same name ('microsoft pc-joystick driver'). This makes configuration
|
||||
// totally useless, so append an ID to the name. We can't test for the
|
||||
// name, since the name is even translated.
|
||||
name = name + " " + StringUtils::toString(id).c_str();
|
||||
// totally useless, so append an ID to the name. We can't test for the
|
||||
// name, since the name is even translated.
|
||||
name = name + " " + StringUtils::toString(id).c_str();
|
||||
#endif
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
@ -180,10 +179,12 @@ GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/**
|
||||
* Check if we already have a config object for gamepad 'irr_id' as reported by irrLicht
|
||||
* If no, create one. Returns true if new configuration was created, otherwise false.
|
||||
* Check if we already have a config object for gamepad 'irr_id' as reported by
|
||||
* irrLicht, If no, create one. Returns true if new configuration was created,
|
||||
* otherwise false.
|
||||
*/
|
||||
bool DeviceManager::getConfigForGamepad(const int irr_id, const core::stringc& name, GamepadConfig **config)
|
||||
bool DeviceManager::getConfigForGamepad(const int irr_id, const core::stringc& name,
|
||||
GamepadConfig **config)
|
||||
{
|
||||
bool found = false;
|
||||
bool configCreated = false;
|
||||
@ -210,9 +211,8 @@ bool DeviceManager::getConfigForGamepad(const int irr_id, const core::stringc& n
|
||||
#ifdef ENABLE_WIIUSE
|
||||
else // Wiimotes have a higher ID and do not refer to m_irrlicht_gamepads
|
||||
{
|
||||
*config = new GamepadConfig( name.c_str(),
|
||||
WIIMOTE_AXES,
|
||||
WIIMOTE_BUTTONS );
|
||||
// The Wiimote manager will set number of buttons and axis
|
||||
*config = new GamepadConfig(name.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -430,7 +430,7 @@ InputDevice* DeviceManager::getLatestUsedDevice()
|
||||
// -----------------------------------------------------------------------------
|
||||
void DeviceManager::clearLatestUsedDevice()
|
||||
{
|
||||
m_latest_used_device = NULL;
|
||||
m_latest_used_device = NULL;
|
||||
} // clearLatestUsedDevice
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -56,6 +56,8 @@ private:
|
||||
PtrVector<GamePadDevice, HOLD> m_gamepads;
|
||||
PtrVector<KeyboardConfig, HOLD> m_keyboard_configs;
|
||||
PtrVector<GamepadConfig, HOLD> m_gamepad_configs;
|
||||
|
||||
/** The list of all joysticks that were found and activated. */
|
||||
core::array<SJoystickInfo> m_irrlicht_gamepads;
|
||||
InputDevice* m_latest_used_device;
|
||||
PlayerAssignMode m_assign_mode;
|
||||
|
@ -75,7 +75,7 @@ bool KeyboardDevice::processAndMapInput(const int id,
|
||||
|
||||
|
||||
GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
const int axis_count, const int btnAmount,
|
||||
const int axis_count, const int button_count,
|
||||
GamepadConfig *configuration)
|
||||
{
|
||||
m_type = DT_GAMEPAD;
|
||||
@ -86,7 +86,7 @@ GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
m_prevAxisDirections = new Input::AxisDirection[axis_count];
|
||||
m_prevAxisValue = new int[axis_count];
|
||||
m_axis_ok = new bool[axis_count];
|
||||
m_button_count = btnAmount;
|
||||
m_button_count = button_count;
|
||||
m_index = irrIndex;
|
||||
m_name = name;
|
||||
|
||||
|
180
src/input/wiimote.cpp
Normal file
180
src/input/wiimote.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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 3
|
||||
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifdef ENABLE_WIIUSE
|
||||
|
||||
#include "input/wiimote.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "wiiuse.h"
|
||||
|
||||
|
||||
|
||||
Wiimote::Wiimote(wiimote_t* wiimote_handle, int wiimote_id,
|
||||
GamepadConfig* gamepad_config)
|
||||
{
|
||||
m_wiimote_handle = wiimote_handle;
|
||||
m_wiimote_id = wiimote_id;
|
||||
resetIrrEvent();
|
||||
|
||||
m_connected = true;
|
||||
|
||||
// Create the corresponding gamepad device
|
||||
irr::core::stringc gamepad_name = irr::core::stringc("Wiimote ") +
|
||||
StringUtils::toString(wiimote_id).c_str();
|
||||
|
||||
gamepad_config->setPlugged();
|
||||
// Determine number of bits in the bit mask of all buttons.
|
||||
int button_count = (int)( log((float)WIIMOTE_BUTTON_ALL) / log(2.0f))+1;
|
||||
|
||||
m_gamepad_device = new GamePadDevice(getIrrId(),
|
||||
gamepad_name.c_str(),
|
||||
/*num axes*/ 1,
|
||||
button_count,
|
||||
gamepad_config );
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
device_manager->addGamepad(m_gamepad_device);
|
||||
|
||||
} // Wiimote
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Wiimote::~Wiimote()
|
||||
{
|
||||
} // ~Wiimote
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void Wiimote::resetIrrEvent()
|
||||
{
|
||||
irr::SEvent &event = m_irr_event.getData();
|
||||
event.EventType = irr::EET_JOYSTICK_INPUT_EVENT;
|
||||
for(int i=0 ; i < irr::SEvent::SJoystickEvent::NUMBER_OF_AXES ; i++)
|
||||
event.JoystickEvent.Axis[i] = 0;
|
||||
event.JoystickEvent.Joystick = getIrrId();
|
||||
event.JoystickEvent.POV = 65535;
|
||||
event.JoystickEvent.ButtonStates = 0;
|
||||
} // resetIrrEvent
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Called from the update thread: takes the wiimote state and
|
||||
*/
|
||||
void Wiimote::update()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(UserConfigParams::m_wiimote_debug)
|
||||
{
|
||||
Log::verbose("wiimote", "pitch: %f yaw %f roll %f",
|
||||
m_wiimote_handle->orient.pitch,
|
||||
m_wiimote_handle->orient.yaw,
|
||||
m_wiimote_handle->orient.roll);
|
||||
}
|
||||
#endif
|
||||
|
||||
float normalized_angle = -m_wiimote_handle->orient.pitch / UserConfigParams::m_wiimote_max;
|
||||
if(normalized_angle<-1.0f)
|
||||
normalized_angle = -1.0f;
|
||||
else if(normalized_angle>1.0f)
|
||||
normalized_angle = 1.0f;
|
||||
|
||||
// Shape the curve that determines steering depending on wiimote angle.
|
||||
// The wiimote value is already normalized to be in [-1,1]. Now use a
|
||||
// weighted linear combination to compute the steering value used in game.
|
||||
float w1 = UserConfigParams::m_wiimote_weight_linear;
|
||||
float w2 = UserConfigParams::m_wiimote_weight_square;
|
||||
float wa = UserConfigParams::m_wiimote_weight_asin;
|
||||
float ws = UserConfigParams::m_wiimote_weight_sin;
|
||||
|
||||
const float sign = normalized_angle >= 0.0f ? 1.0f : -1.0f;
|
||||
const float normalized_angle_2 = w1 * normalized_angle
|
||||
+ w2 * sign*normalized_angle*normalized_angle
|
||||
+ wa * asin(normalized_angle)*(2.0f/M_PI)
|
||||
+ ws * sin(normalized_angle*(M_PI/2.0f));
|
||||
const float JOYSTICK_ABS_MAX_ANGLE = 32766.0f;
|
||||
|
||||
const float angle = normalized_angle_2 * JOYSTICK_ABS_MAX_ANGLE;
|
||||
|
||||
m_irr_event.lock();
|
||||
{
|
||||
|
||||
irr::SEvent::SJoystickEvent &ev = m_irr_event.getData().JoystickEvent;
|
||||
ev.Axis[SEvent::SJoystickEvent::AXIS_X] =
|
||||
(irr::s16)(irr::core::clamp(angle, -JOYSTICK_ABS_MAX_ANGLE,
|
||||
+JOYSTICK_ABS_MAX_ANGLE));
|
||||
// --------------------- Wiimote buttons --------------------
|
||||
// Copy the wiimote button structure, but mask out the non-button
|
||||
// bits (4 bits of the button structure are actually bits for the
|
||||
// accelerator).
|
||||
ev.ButtonStates = m_wiimote_handle->btns & WIIMOTE_BUTTON_ALL;
|
||||
}
|
||||
m_irr_event.unlock();
|
||||
|
||||
#ifdef DEBUG
|
||||
if(UserConfigParams::m_wiimote_debug)
|
||||
printDebugInfo();
|
||||
#endif
|
||||
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Prints debug information to Log::verbose about accelerometer and button
|
||||
* states.
|
||||
*/
|
||||
void Wiimote::printDebugInfo() const
|
||||
{
|
||||
struct WiimoteAction
|
||||
{
|
||||
int wiimote_action_id;
|
||||
const char* wiimote_action_name;
|
||||
}; // struct WiimoteAction
|
||||
|
||||
static WiimoteAction wiimote_actions[] = {
|
||||
{WIIMOTE_BUTTON_LEFT, "WIIMOTE_BUTTON_LEFT" },
|
||||
{WIIMOTE_BUTTON_RIGHT, "WIIMOTE_BUTTON_RIGHT"},
|
||||
{WIIMOTE_BUTTON_UP, "WIIMOTE_BUTTON_UP" },
|
||||
{WIIMOTE_BUTTON_DOWN, "WIIMOTE_BUTTON_DOWN" },
|
||||
{WIIMOTE_BUTTON_A, "WIIMOTE_BUTTON_A" },
|
||||
{WIIMOTE_BUTTON_B, "WIIMOTE_BUTTON_B" },
|
||||
{WIIMOTE_BUTTON_PLUS, "WIIMOTE_BUTTON_PLUS" },
|
||||
{WIIMOTE_BUTTON_MINUS, "WIIMOTE_BUTTON_MINUS"},
|
||||
{WIIMOTE_BUTTON_ONE, "WIIMOTE_BUTTON_ONE" },
|
||||
{WIIMOTE_BUTTON_TWO, "WIIMOTE_BUTTON_TWO" },
|
||||
{WIIMOTE_BUTTON_HOME, "WIIMOTE_BUTTON_HOME" },
|
||||
}; // wiimote_actions
|
||||
|
||||
const int count = sizeof(wiimote_actions)/sizeof(WiimoteAction);
|
||||
for(unsigned int i=0 ; i<count; i++)
|
||||
{
|
||||
if(IS_PRESSED(m_wiimote_handle, wiimote_actions[i].wiimote_action_id))
|
||||
{
|
||||
Log::verbose("wiimote", "%d: pressed button %s -> button id: %d",
|
||||
m_wiimote_id, wiimote_actions[i].wiimote_action_name,
|
||||
i);
|
||||
}
|
||||
} // for i < count
|
||||
} // printDebugInfo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Thread-safe reading of the last updated event
|
||||
*/
|
||||
irr::SEvent Wiimote::getIrrEvent()
|
||||
{
|
||||
return m_irr_event.getAtomic();
|
||||
} // getIrrEvent
|
||||
|
||||
#endif // ENABLE_WIIUSE
|
87
src/input/wiimote.hpp
Normal file
87
src/input/wiimote.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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 3
|
||||
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef WIIMOTE_HPP
|
||||
#define WIIMOTE_HPP
|
||||
|
||||
#ifdef ENABLE_WIIUSE
|
||||
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
#include "IEventReceiver.h"
|
||||
|
||||
struct wiimote_t;
|
||||
class GamepadConfig;
|
||||
class GamePadDevice;
|
||||
|
||||
/** Wiimote device class */
|
||||
class Wiimote
|
||||
{
|
||||
private:
|
||||
/** Offset for wiimote irrlicht gamepads ids, to make sure any wiimote
|
||||
* can be identified by having this or a larger id. */
|
||||
static const int WIIMOTE_START_IRR_ID = 32;
|
||||
|
||||
/** Handle to the corresponding WiiUse wiimote handle */
|
||||
wiimote_t* m_wiimote_handle;
|
||||
|
||||
/** Index of this element the arrays of wiimotes */
|
||||
int m_wiimote_id;
|
||||
|
||||
/** Corresponding gamepad managed by the DeviceManager */
|
||||
GamePadDevice* m_gamepad_device;
|
||||
|
||||
/** Corresponding Irrlicht gamepad event */
|
||||
Synchronised<irr::SEvent> m_irr_event;
|
||||
|
||||
/** Whether the wiimote received a "disconnected" event */
|
||||
bool m_connected;
|
||||
|
||||
void resetIrrEvent();
|
||||
void printDebugInfo() const;
|
||||
|
||||
public:
|
||||
/** Resets internal state and creates the corresponding gamepad device */
|
||||
Wiimote(wiimote_t* wiimote_handle, int wiimote_id,
|
||||
GamepadConfig* gamepad_config);
|
||||
~Wiimote();
|
||||
|
||||
/** To be called when the wiimote becomes unused */
|
||||
void cleanup();
|
||||
void update();
|
||||
irr::SEvent getIrrEvent();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns the wiiuse handle of this wiimote. */
|
||||
wiimote_t* getWiimoteHandle() const { return m_wiimote_handle; }
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns true if this wiimote is connected. */
|
||||
bool isConnected() const { return m_connected; }
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Sets the connection state of this wiimote. */
|
||||
void setConnected(bool connected) { m_connected=connected; }
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns the irrlicht id for this wiimote. The wiimote ids have a higher
|
||||
* index than any gamepad reported by irrlicht.*/
|
||||
int Wiimote::getIrrId() { return m_wiimote_id + WIIMOTE_START_IRR_ID; }
|
||||
|
||||
}; // class Wiimote
|
||||
|
||||
#endif
|
||||
|
||||
#endif // WIIMOTE_HPP
|
@ -24,6 +24,7 @@
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/wiimote.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
@ -31,233 +32,18 @@
|
||||
|
||||
WiimoteManager* wiimote_manager;
|
||||
|
||||
const int WIIMOTE_AXES = 1; // only use one axis, for turning
|
||||
const int WIIMOTE_BUTTONS = 12; // A, B, left, right, top, bottom, 1, 2, (+), (-), home
|
||||
|
||||
bool WiimoteManager::m_enabled = false;
|
||||
|
||||
/** Irrlicht device IDs for the wiimotes start at this value */
|
||||
static const int WIIMOTE_START_IRR_ID = 32;
|
||||
static const float JOYSTICK_ABS_MAX_ANGLE = 32766.0f;
|
||||
|
||||
// ============================ Helper functions ============================
|
||||
// -----------------------------------------------------------------------------
|
||||
static int wiimoteIdToIrrId(int wiimote_id)
|
||||
{
|
||||
return wiimote_id + WIIMOTE_START_IRR_ID;
|
||||
} // wiimoteIdToIrrId
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
static void resetIrrEvent(irr::SEvent* event, int irr_id)
|
||||
{
|
||||
event->EventType = irr::EET_JOYSTICK_INPUT_EVENT;
|
||||
for(int i=0 ; i < SEvent::SJoystickEvent::NUMBER_OF_AXES ; i++)
|
||||
event->JoystickEvent.Axis[i] = 0;
|
||||
event->JoystickEvent.Joystick = irr_id;
|
||||
event->JoystickEvent.POV = 65535;
|
||||
event->JoystickEvent.ButtonStates = 0;
|
||||
} // resetIrrEvent
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
struct WiimoteAction
|
||||
{
|
||||
int button_id;
|
||||
int wiimote_action_id;
|
||||
const char* wiimote_action_name;
|
||||
}; // struct WiimoteAction
|
||||
|
||||
static WiimoteAction wiimote_actions[] = {
|
||||
{0, WIIMOTE_BUTTON_LEFT, "WIIMOTE_BUTTON_LEFT"},
|
||||
{1, WIIMOTE_BUTTON_RIGHT, "WIIMOTE_BUTTON_RIGHT"},
|
||||
{2, WIIMOTE_BUTTON_UP, "WIIMOTE_BUTTON_UP"},
|
||||
{3, WIIMOTE_BUTTON_DOWN, "WIIMOTE_BUTTON_DOWN"},
|
||||
{4, WIIMOTE_BUTTON_A, "WIIMOTE_BUTTON_A"},
|
||||
{5, WIIMOTE_BUTTON_B, "WIIMOTE_BUTTON_B"},
|
||||
{6, WIIMOTE_BUTTON_PLUS, "WIIMOTE_BUTTON_PLUS"},
|
||||
{7, WIIMOTE_BUTTON_MINUS, "WIIMOTE_BUTTON_MINUS"},
|
||||
{8, WIIMOTE_BUTTON_ONE, "WIIMOTE_BUTTON_ONE"},
|
||||
{9, WIIMOTE_BUTTON_TWO, "WIIMOTE_BUTTON_TWO"},
|
||||
{10, WIIMOTE_BUTTON_HOME, "WIIMOTE_BUTTON_HOME"},
|
||||
}; // wiimote_actions
|
||||
|
||||
static int getButtonId(int wiimote_action_id)
|
||||
{
|
||||
for(unsigned int i=0 ; i < sizeof(wiimote_actions)/sizeof(WiimoteAction) ; i++)
|
||||
if(wiimote_actions[i].wiimote_action_id == wiimote_action_id)
|
||||
return wiimote_actions[i].button_id;
|
||||
assert(false && "shouldn't happen");
|
||||
return -1;
|
||||
} // getButtonId
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
static void setWiimoteBindings(GamepadConfig* gamepad_config)
|
||||
{
|
||||
gamepad_config->setBinding(PA_STEER_LEFT, Input::IT_STICKMOTION, 0, Input::AD_NEGATIVE);
|
||||
gamepad_config->setBinding(PA_STEER_RIGHT, Input::IT_STICKMOTION, 0, Input::AD_POSITIVE);
|
||||
gamepad_config->setBinding(PA_ACCEL, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_TWO));
|
||||
gamepad_config->setBinding(PA_BRAKE, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_ONE));
|
||||
gamepad_config->setBinding(PA_FIRE, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_RIGHT));
|
||||
gamepad_config->setBinding(PA_NITRO, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_UP));
|
||||
gamepad_config->setBinding(PA_DRIFT, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_B));
|
||||
gamepad_config->setBinding(PA_RESCUE, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_PLUS));
|
||||
gamepad_config->setBinding(PA_LOOK_BACK, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_DOWN));
|
||||
gamepad_config->setBinding(PA_PAUSE_RACE, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_HOME));
|
||||
|
||||
gamepad_config->setBinding(PA_MENU_UP, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_RIGHT));
|
||||
gamepad_config->setBinding(PA_MENU_DOWN, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_LEFT));
|
||||
gamepad_config->setBinding(PA_MENU_LEFT, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_UP));
|
||||
gamepad_config->setBinding(PA_MENU_RIGHT, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_DOWN));
|
||||
gamepad_config->setBinding(PA_MENU_SELECT, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_TWO));
|
||||
gamepad_config->setBinding(PA_MENU_CANCEL, Input::IT_STICKBUTTON, getButtonId(WIIMOTE_BUTTON_ONE));
|
||||
} // setWiimoteBindings
|
||||
|
||||
// ============================ Wiimote device implementation ============================
|
||||
Wiimote::Wiimote()
|
||||
{
|
||||
m_wiimote_handle = NULL;
|
||||
m_wiimote_id = -1;
|
||||
m_gamepad_device = NULL;
|
||||
resetIrrEvent(&m_irr_event, 0);
|
||||
m_connected = false;
|
||||
|
||||
pthread_mutex_init(&m_event_mutex, NULL);
|
||||
} // Wiimote
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Wiimote::~Wiimote()
|
||||
{
|
||||
pthread_mutex_destroy(&m_event_mutex);
|
||||
} // ~Wiimote
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Resets internal state and creates the corresponding gamepad device */
|
||||
void Wiimote::init(wiimote_t* wiimote_handle, int wiimote_id, GamepadConfig* gamepad_config)
|
||||
{
|
||||
m_wiimote_handle = wiimote_handle;
|
||||
m_wiimote_id = wiimote_id;
|
||||
int irr_id = wiimoteIdToIrrId(wiimote_id);
|
||||
resetIrrEvent(&m_irr_event, irr_id);
|
||||
|
||||
m_connected = true;
|
||||
|
||||
// Create the corresponding gamepad device
|
||||
|
||||
core::stringc gamepad_name = core::stringc("Wiimote ") + StringUtils::toString(wiimote_id).c_str();
|
||||
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
gamepad_config->setPlugged();
|
||||
m_gamepad_device = new GamePadDevice(irr_id,
|
||||
gamepad_name.c_str(),
|
||||
WIIMOTE_AXES,
|
||||
WIIMOTE_BUTTONS,
|
||||
gamepad_config );
|
||||
device_manager->addGamepad(m_gamepad_device);
|
||||
} // init
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Called from the update thread: updates the Irrlicht event from the wiimote state */
|
||||
void Wiimote::updateIrrEvent()
|
||||
{
|
||||
pthread_mutex_lock(&m_event_mutex);
|
||||
|
||||
// Simulate an Irrlicht joystick event
|
||||
resetIrrEvent(&m_irr_event, wiimoteIdToIrrId(m_wiimote_id));
|
||||
#ifdef DEBUG
|
||||
if(UserConfigParams::m_wiimote_debug)
|
||||
{
|
||||
Log::verbose("wiimote", "pitch: %f yaw %f roll %f",
|
||||
m_wiimote_handle->orient.pitch,
|
||||
m_wiimote_handle->orient.yaw,
|
||||
m_wiimote_handle->orient.roll);
|
||||
}
|
||||
#endif
|
||||
|
||||
float normalized_angle = -m_wiimote_handle->orient.pitch / UserConfigParams::m_wiimote_max;
|
||||
if(normalized_angle<-1.0f)
|
||||
normalized_angle = -1.0f;
|
||||
else if(normalized_angle>1.0f)
|
||||
normalized_angle = 1.0f;
|
||||
|
||||
// Shape the curve that determines steering depending on wiimote angle.
|
||||
// The wiimote value is already normalized to be in [-1,1]. Now use a
|
||||
// weighted linear combination to compute the steering value used in game.
|
||||
float w1 = UserConfigParams::m_wiimote_weight_linear;
|
||||
float w2 = UserConfigParams::m_wiimote_weight_square;
|
||||
float wa = UserConfigParams::m_wiimote_weight_asin;
|
||||
float ws = UserConfigParams::m_wiimote_weight_sin;
|
||||
|
||||
const float sign = normalized_angle >= 0.0f ? 1.0f : -1.0f;
|
||||
const float normalized_angle_2 = w1 * normalized_angle
|
||||
+ w2 * sign*normalized_angle * normalized_angle
|
||||
+ wa * asin(normalized_angle)*(2.0f/M_PI)
|
||||
+ ws * sin(normalized_angle*(M_PI/2.0f));
|
||||
const float angle = normalized_angle_2 * JOYSTICK_ABS_MAX_ANGLE;
|
||||
m_irr_event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X] =
|
||||
(irr::s16)(irr::core::clamp(angle, -JOYSTICK_ABS_MAX_ANGLE, +JOYSTICK_ABS_MAX_ANGLE));
|
||||
|
||||
// --------------------- Wiimote buttons --------------------
|
||||
// Send button states
|
||||
for(unsigned int i=0 ; i < sizeof(wiimote_actions)/sizeof(WiimoteAction) ; i++)
|
||||
{
|
||||
if(IS_PRESSED(m_wiimote_handle, wiimote_actions[i].wiimote_action_id))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(UserConfigParams::m_wiimote_debug)
|
||||
Log::verbose("wiimote", "%d: pressed button %s -> button id: %d\n",
|
||||
m_wiimote_id,
|
||||
wiimote_actions[i].wiimote_action_name,
|
||||
wiimote_actions[i].button_id);
|
||||
#endif
|
||||
m_irr_event.JoystickEvent.ButtonStates |= (1<<(wiimote_actions[i].button_id));
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ Nunchuk ----------------------
|
||||
/* if (m_wiimote_handle->exp.type == EXP_NUNCHUK)
|
||||
{
|
||||
struct nunchuk_t* nc = (nunchuk_t*)&m_wiimote_handle->exp.nunchuk;
|
||||
|
||||
if (IS_PRESSED(nc, NUNCHUK_BUTTON_C))
|
||||
{
|
||||
printf("DEBUG: C\n");
|
||||
m_irr_event.JoystickEvent.ButtonStates |= (1<<12);
|
||||
}
|
||||
if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z))
|
||||
{
|
||||
printf("DEBUG: Z\n");
|
||||
m_irr_event.JoystickEvent.ButtonStates |= (1<<13);
|
||||
}
|
||||
|
||||
printf("nunchuk roll = %f\n", nc->orient.roll);
|
||||
printf("nunchuk pitch = %f\n", nc->orient.pitch);
|
||||
printf("nunchuk yaw = %f\n", nc->orient.yaw);
|
||||
|
||||
printf("nunchuk joystick angle: %f\n", nc->js.ang);
|
||||
printf("nunchuk joystick magnitude: %f\n", nc->js.mag);
|
||||
}
|
||||
*/
|
||||
pthread_mutex_unlock(&m_event_mutex);
|
||||
} // updateIrrEvent
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::SEvent Wiimote::getIrrEvent()
|
||||
{
|
||||
irr::SEvent event;
|
||||
|
||||
pthread_mutex_lock(&m_event_mutex);
|
||||
event = m_irr_event;
|
||||
pthread_mutex_unlock(&m_event_mutex);
|
||||
|
||||
return event;
|
||||
} // getIrrEvent
|
||||
|
||||
// ============================ Wiimote manager implementation ============================
|
||||
WiimoteManager::WiimoteManager()
|
||||
{
|
||||
m_all_wiimote_handles = NULL;
|
||||
m_nb_wiimotes = 0;
|
||||
|
||||
#ifdef WIIMOTE_THREADING
|
||||
m_shut = false;
|
||||
#endif
|
||||
} // WiimoteManager
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -287,10 +73,10 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
return;
|
||||
|
||||
// Try to connect to all found wiimotes
|
||||
m_nb_wiimotes = wiiuse_connect(m_all_wiimote_handles, nb_found_wiimotes);
|
||||
int nb_wiimotes = wiiuse_connect(m_all_wiimote_handles, nb_found_wiimotes);
|
||||
|
||||
// Couldn't connect to any wiimote?
|
||||
if(m_nb_wiimotes == 0)
|
||||
if(nb_wiimotes == 0)
|
||||
return;
|
||||
|
||||
// ---------------------------------------------------
|
||||
@ -298,149 +84,195 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
GamepadConfig* gamepad_config = NULL;
|
||||
|
||||
device_manager->getConfigForGamepad(WIIMOTE_START_IRR_ID, "Wiimote", &gamepad_config);
|
||||
device_manager->getConfigForGamepad(WIIMOTE_START_IRR_ID, "Wiimote",
|
||||
&gamepad_config);
|
||||
int num_buttons = (int)( log((float)WIIMOTE_BUTTON_ALL) / log(2.0f))+1;
|
||||
gamepad_config->setNumberOfButtons(num_buttons);
|
||||
gamepad_config->setNumberOfAxis(1);
|
||||
|
||||
setWiimoteBindings(gamepad_config);
|
||||
|
||||
// Initialize all Wiimotes, which in turn create their associated GamePadDevices
|
||||
for(int i=0 ; i < m_nb_wiimotes ; i++)
|
||||
// Initialize all Wiimotes, which in turn create their
|
||||
// associated GamePadDevices
|
||||
for(int i=0 ; i < nb_wiimotes ; i++)
|
||||
{
|
||||
m_wiimotes[i].init(m_all_wiimote_handles[i], i, gamepad_config);
|
||||
m_wiimotes.push_back(new Wiimote(m_all_wiimote_handles[i], i,
|
||||
gamepad_config ));
|
||||
} // end for
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Set the LEDs and rumble for 0.2s
|
||||
int leds[] = {WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, WIIMOTE_LED_4};
|
||||
for(int i=0 ; i < m_nb_wiimotes ; i++)
|
||||
for(unsigned int i=0 ; i < m_wiimotes.size(); i++)
|
||||
{
|
||||
wiimote_t* wiimote_handle = m_wiimotes[i].getWiimoteHandle();
|
||||
wiimote_t* wiimote_handle = m_wiimotes[i]->getWiimoteHandle();
|
||||
wiiuse_set_leds(wiimote_handle, leds[i]);
|
||||
wiiuse_rumble(wiimote_handle, 1);
|
||||
}
|
||||
|
||||
irr_driver->getDevice()->sleep(200);
|
||||
|
||||
for(int i=0 ; i < m_nb_wiimotes ; i++)
|
||||
for(unsigned int i=0 ; i < m_wiimotes.size(); i++)
|
||||
{
|
||||
wiimote_t* wiimote_handle = m_wiimotes[i].getWiimoteHandle();
|
||||
wiimote_t* wiimote_handle = m_wiimotes[i]->getWiimoteHandle();
|
||||
wiiuse_rumble(wiimote_handle, 0);
|
||||
}
|
||||
|
||||
// TODO: only enable accelerometer during race
|
||||
enableAccelerometer(true);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Launch the update thread
|
||||
#ifdef WIIMOTE_THREADING
|
||||
m_shut = false;
|
||||
|
||||
pthread_create(&m_thread, NULL, &threadFuncWrapper, this);
|
||||
#endif
|
||||
} // launchDetection
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines the button number based on the bitmask of a button. E.g.
|
||||
* 0x0004 (= 00100_2) is converted into 3.
|
||||
*/
|
||||
int getButton(int n)
|
||||
{
|
||||
return (int)(log((float)n)/log(2.0f));
|
||||
} // getButton
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Defines the key bindings for a wiimote for the device manager.
|
||||
* \param gamepad_config The configuration to be defined.
|
||||
*/
|
||||
void WiimoteManager::setWiimoteBindings(GamepadConfig* gamepad_config)
|
||||
{
|
||||
gamepad_config->setBinding(PA_STEER_LEFT, Input::IT_STICKMOTION, 0, Input::AD_NEGATIVE);
|
||||
gamepad_config->setBinding(PA_STEER_RIGHT, Input::IT_STICKMOTION, 0, Input::AD_POSITIVE);
|
||||
gamepad_config->setBinding(PA_ACCEL, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_TWO));
|
||||
gamepad_config->setBinding(PA_BRAKE, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_ONE));
|
||||
gamepad_config->setBinding(PA_FIRE, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_RIGHT));
|
||||
gamepad_config->setBinding(PA_NITRO, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_UP));
|
||||
gamepad_config->setBinding(PA_DRIFT, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_B));
|
||||
gamepad_config->setBinding(PA_RESCUE, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_PLUS));
|
||||
gamepad_config->setBinding(PA_LOOK_BACK, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_DOWN));
|
||||
gamepad_config->setBinding(PA_PAUSE_RACE, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_HOME));
|
||||
|
||||
gamepad_config->setBinding(PA_MENU_UP, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_RIGHT));
|
||||
gamepad_config->setBinding(PA_MENU_DOWN, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_LEFT));
|
||||
gamepad_config->setBinding(PA_MENU_LEFT, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_UP));
|
||||
gamepad_config->setBinding(PA_MENU_RIGHT, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_DOWN));
|
||||
gamepad_config->setBinding(PA_MENU_SELECT, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_TWO));
|
||||
gamepad_config->setBinding(PA_MENU_CANCEL, Input::IT_STICKBUTTON, getButton(WIIMOTE_BUTTON_ONE));
|
||||
} // setWiimoteBindings
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void WiimoteManager::cleanup()
|
||||
{
|
||||
if(m_nb_wiimotes > 0)
|
||||
if(m_wiimotes.size() > 0)
|
||||
{
|
||||
DeviceManager* device_manager = input_manager->getDeviceList();
|
||||
|
||||
GamePadDevice* first_gamepad_device = device_manager->getGamePadFromIrrID(WIIMOTE_START_IRR_ID);
|
||||
GamePadDevice* first_gamepad_device =
|
||||
device_manager->getGamePadFromIrrID(WIIMOTE_START_IRR_ID);
|
||||
assert(first_gamepad_device);
|
||||
|
||||
DeviceConfig* gamepad_config = first_gamepad_device->getConfiguration();
|
||||
DeviceConfig* gamepad_config =
|
||||
first_gamepad_device->getConfiguration();
|
||||
assert(gamepad_config);
|
||||
|
||||
// Remove the wiimote configuration -> automatically removes all linked gamepad devices;
|
||||
// Remove the wiimote configuration -> automatically removes all
|
||||
// linked gamepad devices;
|
||||
device_manager->deleteConfig(gamepad_config);
|
||||
|
||||
// Shut the update thread
|
||||
#ifdef WIIMOTE_THREADING
|
||||
m_shut = true;
|
||||
pthread_join(m_thread, NULL);
|
||||
|
||||
#endif
|
||||
// Cleanup WiiUse
|
||||
wiiuse_cleanup(m_all_wiimote_handles, MAX_WIIMOTES);
|
||||
}
|
||||
|
||||
for(unsigned int i=0; i<m_wiimotes.size(); i++)
|
||||
delete m_wiimotes[i];
|
||||
m_wiimotes.clear();
|
||||
|
||||
// Reset
|
||||
m_all_wiimote_handles = NULL;
|
||||
m_nb_wiimotes = 0;
|
||||
m_shut = false;
|
||||
#ifdef WIIMOTE_THREADING
|
||||
m_shut = false;
|
||||
#endif
|
||||
} // cleanup
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
void WiimoteManager::update()
|
||||
{
|
||||
for(int i=0 ; i < MAX_WIIMOTES ; i++)
|
||||
#ifndef WIIMOTE_THREADING
|
||||
threadFunc();
|
||||
#endif
|
||||
for(unsigned int i=0 ; i < m_wiimotes.size(); i++)
|
||||
{
|
||||
if(m_wiimotes[i].isConnected())
|
||||
{
|
||||
irr::SEvent event = m_wiimotes[i].getIrrEvent();
|
||||
input_manager->input(event);
|
||||
}
|
||||
irr::SEvent event = m_wiimotes[i]->getIrrEvent();
|
||||
input_manager->input(event);
|
||||
}
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Thread update method - wiimotes state is updated in another thread to avoid latency problems */
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Enables or disables the accelerometer in wiimotes (to save battery life).
|
||||
* \param state True if the accelerometer should be enabled.
|
||||
*/
|
||||
void WiimoteManager::enableAccelerometer(bool state)
|
||||
{
|
||||
for (unsigned int i=0; i < m_wiimotes.size(); ++i)
|
||||
{
|
||||
wiiuse_motion_sensing(m_wiimotes[i]->getWiimoteHandle(), state ? 1 : 0);
|
||||
}
|
||||
} // enableAccelerometer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Thread update method - wiimotes state is updated in another thread to
|
||||
* avoid latency problems */
|
||||
void WiimoteManager::threadFunc()
|
||||
{
|
||||
// Enable accelerometer reporting
|
||||
// TODO: this should only be done when needed (i.e when racing)
|
||||
// so as to avoid wasting wiimote batteries.
|
||||
// TODO: this should only be done once, but there have been reports that it didn't
|
||||
// work for some people -> need to find a better fix
|
||||
for (int i=0; i < MAX_WIIMOTES; ++i)
|
||||
{
|
||||
if(m_wiimotes[i].isConnected())
|
||||
wiiuse_motion_sensing(m_wiimotes[i].getWiimoteHandle(), 1);
|
||||
}
|
||||
|
||||
#ifdef WIIMOTE_THREADING
|
||||
while(!m_shut)
|
||||
#endif
|
||||
{
|
||||
if(wiiuse_poll(m_all_wiimote_handles, MAX_WIIMOTES))
|
||||
{
|
||||
for (int i=0; i < MAX_WIIMOTES; ++i)
|
||||
for (unsigned int i=0; i < m_wiimotes.size(); ++i)
|
||||
{
|
||||
if(!m_wiimotes[i].isConnected())
|
||||
continue;
|
||||
|
||||
/*
|
||||
if(WIIUSE_USING_EXP(m_wiimotes[i].getWiimoteHandle()))
|
||||
{
|
||||
if(WIIUSE_USING_EXP(wm))
|
||||
wiiuse_set_motion_plus(m_wiimotes[i].getWiimoteHandle(), 2); // nunchuck pass-through
|
||||
else
|
||||
wiiuse_set_motion_plus(m_wiimotes[i].getWiimoteHandle(), 1); // standalone
|
||||
}
|
||||
*/
|
||||
switch (m_all_wiimote_handles[i]->event)
|
||||
{
|
||||
case WIIUSE_EVENT:
|
||||
m_wiimotes[i].updateIrrEvent();
|
||||
m_wiimotes[i]->update();
|
||||
//printf("DEBUG: wiimote event\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_STATUS:
|
||||
//printf("DEBUG: status event\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_DISCONNECT:
|
||||
case WIIUSE_UNEXPECTED_DISCONNECT:
|
||||
//printf("DEBUG: wiimote disconnected\n");
|
||||
m_wiimotes[i].setConnected(false);
|
||||
m_wiimotes[i]->setConnected(false);
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_READ_DATA:
|
||||
//printf("DEBUG: WIIUSE_READ_DATA\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_NUNCHUK_INSERTED:
|
||||
//printf("DEBUG: Nunchuk inserted.\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_CLASSIC_CTRL_INSERTED:
|
||||
//printf("DEBUG: Classic controller inserted.\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
|
||||
//printf("DEBUG: Guitar Hero 3 controller inserted.\n");
|
||||
break;
|
||||
|
||||
|
||||
case WIIUSE_NUNCHUK_REMOVED:
|
||||
case WIIUSE_CLASSIC_CTRL_REMOVED:
|
||||
case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
|
||||
@ -478,7 +310,7 @@ int WiimoteManager::askUserToConnectWiimotes()
|
||||
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
||||
new WiimoteDialogListener(), true);
|
||||
|
||||
return getNbWiimotes();
|
||||
return getNumberOfWiimotes();
|
||||
} // askUserToConnectWiimotes
|
||||
|
||||
// ============================================================================
|
||||
@ -491,7 +323,7 @@ void WiimoteManager::WiimoteDialogListener::onConfirm()
|
||||
|
||||
wiimote_manager->launchDetection(5);
|
||||
|
||||
int nb_wiimotes = wiimote_manager->getNbWiimotes();
|
||||
int nb_wiimotes = wiimote_manager->getNumberOfWiimotes();
|
||||
if(nb_wiimotes > 0)
|
||||
{
|
||||
core::stringw msg = StringUtils::insertValues(
|
||||
|
@ -21,15 +21,14 @@
|
||||
|
||||
#ifdef ENABLE_WIIUSE
|
||||
|
||||
#include "input/wiimote.hpp"
|
||||
#include "states_screens/dialogs/message_dialog.hpp"
|
||||
#include "utils/cpp2011.h"
|
||||
|
||||
#include "IEventReceiver.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
extern const int WIIMOTE_AXES;
|
||||
extern const int WIIMOTE_BUTTONS;
|
||||
|
||||
#define MAX_WIIMOTES 4
|
||||
|
||||
struct wiimote_t;
|
||||
@ -39,49 +38,6 @@ class WiimoteManager;
|
||||
|
||||
extern WiimoteManager* wiimote_manager;
|
||||
|
||||
/** Wiimote device class */
|
||||
class Wiimote
|
||||
{
|
||||
private:
|
||||
/** Handle to the corresponding WiiUse wiimote handle */
|
||||
wiimote_t* m_wiimote_handle;
|
||||
|
||||
/** Index of this element the arrays of wiimotes */
|
||||
int m_wiimote_id;
|
||||
|
||||
/** Corresponding gamepad managed by the DeviceManager */
|
||||
GamePadDevice* m_gamepad_device;
|
||||
|
||||
/** Corresponding Irrlicht gamepad event */
|
||||
irr::SEvent m_irr_event;
|
||||
|
||||
/** Event used for reading and writing the Irrlicht events */
|
||||
pthread_mutex_t m_event_mutex;
|
||||
|
||||
/** Whether the wiimote received a "disconnected" event */
|
||||
bool m_connected;
|
||||
|
||||
public:
|
||||
Wiimote();
|
||||
~Wiimote();
|
||||
|
||||
/** Resets internal state and creates the corresponding gamepad device */
|
||||
void init(wiimote_t* wiimote_handle, int wiimote_id, GamepadConfig* gamepad_config);
|
||||
|
||||
/** To be called when the wiimote becomes unused */
|
||||
void cleanup();
|
||||
|
||||
/** Called from the update thread: updates the Irrlicht event from the wiimote state */
|
||||
void updateIrrEvent();
|
||||
|
||||
/** Thread-safe reading of the last updated event */
|
||||
irr::SEvent getIrrEvent();
|
||||
|
||||
wiimote_t* getWiimoteHandle() const {return m_wiimote_handle;}
|
||||
|
||||
bool isConnected() const {return m_connected;}
|
||||
void setConnected(bool connected) {m_connected=connected;}
|
||||
};
|
||||
|
||||
/** Wiimote manager: handles wiimote connection, disconnection,
|
||||
* gamepad configuration and input handling
|
||||
@ -89,21 +45,32 @@ public:
|
||||
class WiimoteManager
|
||||
{
|
||||
private:
|
||||
Wiimote m_wiimotes[MAX_WIIMOTES];
|
||||
/** List of all connected wiimotes. */
|
||||
std::vector<Wiimote*> m_wiimotes;
|
||||
|
||||
/** WiiUse wiimote handles */
|
||||
wiimote_t** m_all_wiimote_handles;
|
||||
int m_nb_wiimotes;
|
||||
int m_number_wiimotes;
|
||||
|
||||
// While the wiimote code can technically work without threading,
|
||||
// its too slow (high latency), but it is useful for debugging.
|
||||
#define WIIMOTE_THREADING
|
||||
#ifdef WIIMOTE_THREADING
|
||||
/** Wiimote state update thread */
|
||||
pthread_t m_thread;
|
||||
|
||||
/** Shut the update thread? */
|
||||
bool m_shut;
|
||||
#endif
|
||||
|
||||
/** True if wii is enabled via command line option. */
|
||||
static bool m_enabled;
|
||||
|
||||
/** Wiimotes update thread */
|
||||
void threadFunc();
|
||||
static void* threadFuncWrapper(void* data);
|
||||
void setWiimoteBindings(GamepadConfig* gamepad_config);
|
||||
|
||||
public:
|
||||
WiimoteManager();
|
||||
~WiimoteManager();
|
||||
@ -117,15 +84,9 @@ public:
|
||||
void launchDetection(int timeout);
|
||||
void update();
|
||||
void cleanup();
|
||||
|
||||
int getNbWiimotes() const {return m_nb_wiimotes;}
|
||||
|
||||
private:
|
||||
/** Wiimotes update thread */
|
||||
void threadFunc();
|
||||
static void* threadFuncWrapper(void* data);
|
||||
|
||||
public:
|
||||
void enableAccelerometer(bool state);
|
||||
|
||||
/** A simple listener to allow the user to connect wiimotes. It
|
||||
* will display a feedback windows (# wiimotes connected or 'no wiimotes
|
||||
* found').
|
||||
@ -140,7 +101,11 @@ public:
|
||||
* \return Number of wiimotes connected.
|
||||
*/
|
||||
int askUserToConnectWiimotes();
|
||||
};
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of wiimotes connected. */
|
||||
unsigned int getNumberOfWiimotes() const {return m_wiimotes.size();}
|
||||
|
||||
}; // class WiimoteManager
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user