gamepad axes work again

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3423 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2009-04-25 19:26:44 +00:00
parent 6ed09ea3c5
commit 9eea5f5aac
7 changed files with 221 additions and 122 deletions

View File

@@ -398,14 +398,7 @@ void IrrDriver::setAmbientLight(const video::SColor &light)
*/
void IrrDriver::update(float dt)
{
// FIXME: the run() call interferes with the SDL event handling
// currently implemented in STK (since run() converts all SDL events
// into irrlicht events). To avoid re-writing the STK event handling,
// instead of calling run(), we only update the irrlicht timer (which is
// necessary to get animations to work) - that's the only other operation
// happening in run.
if(!m_device->run()) return;
//m_device->getTimer()->tick();
m_device->getVideoDriver()->beginScene(true, true, video::SColor(255,100,101,140));
m_scene_manager->drawAll();

View File

@@ -40,7 +40,9 @@ namespace GUIEngine
}
bool OnEvent (const SEvent &event)
{
if(event.EventType == EET_GUI_EVENT || !StateManager::isGameState())
if(event.EventType == EET_GUI_EVENT ||
(!StateManager::isGameState() && event.EventType != EET_KEY_INPUT_EVENT && event.EventType != EET_JOYSTICK_INPUT_EVENT)
)
{
if(g_current_screen == NULL) return false;
g_current_screen->OnEvent(event);

View File

@@ -9,6 +9,7 @@
#include "gui/widget.hpp"
#include "gui/state_manager.hpp"
#include "io/file_manager.hpp"
#include "input/input.hpp"
using namespace irr;
@@ -349,11 +350,136 @@ Widget* Screen::getLastWidget(ptr_vector<Widget>* within_vector)
#pragma mark irrLicht events
#endif
#define MAX_VALUE 32768
void Screen::processAction(const int action, const unsigned int value)
{
const bool pressedDown = value > MAX_VALUE*2/3;
if(!pressedDown) return;
switch(action)
{
case PA_LEFT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->leftPressed())
transmitEvent(w, w->m_properties[PROP_ID]);
}
break;
case PA_RIGHT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->rightPressed())
transmitEvent(widget_to_call, w->m_properties[PROP_ID]);
}
break;
case PA_ACCEL:
{
IGUIElement *el, *first=NULL, *closest=NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
if(list->getSelected()>0) break;
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), true, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = getLastWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_BRAKE:
{
IGUIElement *el, *first = NULL, *closest = NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
if(list->getSelected() < (int)list->getItemCount()-1) break;
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), false, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = getFirstWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
}
break;
case PA_RESCUE:
StateManager::escapePressed();
break;
case PA_FIRE:
break;
default:
return;
}
}
bool Screen::OnEvent(const SEvent& event)
{
assert(transmitEvent != NULL);
//if (event.EventType != EET_GUI_EVENT) return false;
if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
{
const int key = event.KeyInput.Key;
@@ -361,111 +487,21 @@ bool Screen::OnEvent(const SEvent& event)
switch(key)
{
case KEY_ESCAPE :
StateManager::escapePressed();
break;
case KEY_SPACE :
break;
case KEY_LEFT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->leftPressed())
transmitEvent(w, w->m_properties[PROP_ID]);
break;
}
case KEY_RIGHT:
{
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
if(el == NULL) break;
Widget* w = getWidget( el->getID() );
if(w == NULL) break;
Widget* widget_to_call = w;
/* Find topmost parent. Stop looping if a widget event handler's is itself, to not fall
in an infinite loop (this can happen e.g. in checkboxes, where they need to be
notified of clicks onto themselves so they can toggle their state. ) */
while(widget_to_call->m_event_handler != NULL && widget_to_call->m_event_handler != widget_to_call)
widget_to_call = widget_to_call->m_event_handler;
if(widget_to_call->rightPressed())
transmitEvent(widget_to_call, w->m_properties[PROP_ID]);
break;
}
case KEY_UP:
{
IGUIElement *el, *first=NULL, *closest=NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
if(list->getSelected()>0) break;
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), true, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = getLastWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
return true;
}
break;
case KEY_DOWN:
{
IGUIElement *el, *first = NULL, *closest = NULL;
el = GUIEngine::getGUIEnv()->getFocus();
Widget* w = (el == NULL) ? NULL : getWidget( el->getID() );
// list widgets are a bit special, because up/down keys are also used
// to navigate between various list items, not only to navigate between
// components
if(w != NULL && w->m_type == WTYPE_LIST)
{
IGUIListBox* list = dynamic_cast<IGUIListBox*>(w->m_element);
assert(list != NULL);
if(list->getSelected() < (int)list->getItemCount()-1) break;
}
if(el != NULL && el->getTabGroup() != NULL &&
el->getTabGroup()->getNextElement(el->getTabOrder(), false, false, first, closest))
{
GUIEngine::getGUIEnv()->setFocus(closest);
}
else
{
// select the first widget
Widget* w = getFirstWidget();
if(w != NULL) GUIEngine::getGUIEnv()->setFocus( w->m_element );
}
return true;
}
break;
}
//std::cout << "key!" << std::endl;

View File

@@ -52,6 +52,8 @@ namespace GUIEngine
void elementsWereDeleted(ptr_vector<Widget>* within_vector = NULL);
virtual bool OnEvent(const SEvent& event);
void processAction(const int action, const unsigned int value);
};
}

View File

@@ -40,7 +40,7 @@ bool DeviceManager::initGamePadSupport()
}
// -----------------------------------------------------------------------------
/**
* Check if we already have a config object for joystick 'sdl_id' as reported by SDL
* Check if we already have a config object for joystick 'irr_id' as reported by irrLicht
* If yes, 'open' the gamepad. If no, create one. Returns whether a new gamepad was created.
*/
bool DeviceManager::checkForGamePad(const int irr_id)

View File

@@ -41,6 +41,7 @@
#include "karts/kart.hpp"
#include "history.hpp"
#include "gui/race_gui.hpp"
#include "gui/screen.hpp"
#include "sdl_manager.hpp"
InputManager *input_manager;
@@ -186,7 +187,7 @@ InputManager::~InputManager()
#define MAX_VALUE 32768
/*
void InputManager::postIrrLichtMouseEvent(irr::EMOUSE_INPUT_EVENT type, const int x, const int y)
{
irr::SEvent::SMouseInput evt;
@@ -201,7 +202,7 @@ void InputManager::postIrrLichtMouseEvent(irr::EMOUSE_INPUT_EVENT type, const in
GUIEngine::getDevice()->postEventFromUser(wrapper);
}
*/
// TODO - make this do something
void InputManager::handleStaticAction(int key, int value)
{
@@ -291,7 +292,7 @@ void InputManager::input(Input::InputType type, int id0, int id1, int id2,
const bool action_found = m_device_manager->mapInputToPlayerAndAction( type, id0, id1, id2, value, &player, &action );
std::cout << "Input code=" << id0 << " found=" << action_found << std::endl;
// std::cout << "Input code=" << id0 << " found=" << action_found << std::endl;
//GameAction ga = m_action_map->getEntry(type, id0, id1, id2);
#if 0 // TODO - input sensing
@@ -341,7 +342,28 @@ void InputManager::input(Input::InputType type, int id0, int id1, int id2,
#endif
if (action_found)
{
RaceManager::getWorld()->getLocalPlayerKart(player)->action(action, abs(value));
if(StateManager::isGameState())
RaceManager::getWorld()->getLocalPlayerKart(player)->action(action, abs(value));
else
{
// reset timer when released
if( abs(value) == 0 )
{
m_timer_in_use = false;
m_timer = 0;
}
// menu input
if(!m_timer_in_use)
{
if(abs(value) > MAX_VALUE*2/3)
{
m_timer_in_use = true;
m_timer = 0.25;
}
GUIEngine::getCurrentScreen()->processAction(action, abs(value));
}
}
}
else if(type == Input::IT_KEYBOARD)
{
@@ -351,17 +373,10 @@ void InputManager::input(Input::InputType type, int id0, int id1, int id2,
} // input
//-----------------------------------------------------------------------------
/** Reads the SDL event loop, does some tricks with certain values and calls
* input() if appropriate.
*
* Digital inputs get the value of 32768 when pressed (key/button press,
* digital axis) because this is what SDL provides. Relative mouse inputs
* which do not fit into this scheme are converted to match. This is done to
* relieve the KartAction implementor from the need to think about different
* input devices and how SDL treats them. The same input gets the value of 0
* when released.
*
* Analog axes can have any value from [0, 32768].
/**
* Called on keyboard events [indirectly] by irrLicht
*
* Analog axes can have any value from [-32768, 32767].
*
* There are no negative values. Instead this is reported as an axis with a
* negative direction. This simplifies input configuration and allows greater
@@ -370,16 +385,67 @@ void InputManager::input(Input::InputType type, int id0, int id1, int id2,
*/
void InputManager::input(const SEvent& event)
{
std::cout << "input event\n";
if(event.EventType == EET_JOYSTICK_INPUT_EVENT)
{
/*
std::cout << "x=" << event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X]
<< " y=" << event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Y]
<< " 1=" << event.JoystickEvent.IsButtonPressed(0)
<< " 2=" << event.JoystickEvent.IsButtonPressed(1)
<< " 3=" << event.JoystickEvent.IsButtonPressed(2)
<< " 4=" << event.JoystickEvent.IsButtonPressed(3) << std::endl;
*/
// Axes - FIXME, instead of checking all of them, ask the bindings which to poll
for(int axis_id=0; axis_id<SEvent::SJoystickEvent::NUMBER_OF_AXES ; axis_id++)
{
int value = event.JoystickEvent.Axis[axis_id];
// work around irrLicht bug. FIXME - get it fixed and remove this
if(value == -32768) continue; // ignore bogus values given by irrlicht
if(user_config->m_gamepad_debug)
{
printf("axis motion: gamepad_id=%d axis=%d value=%d\n",
event.JoystickEvent.Joystick, axis_id, value);
}
// FIXME - AD_NEGATIVE/AD_POSITIVE are probably useless since value contains that info too
if(value < 0)
input(Input::IT_STICKMOTION, event.JoystickEvent.Joystick , axis_id, Input::AD_NEGATIVE, value);
else
input(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, axis_id, Input::AD_POSITIVE, value);
}
/*
case SDL_JOYAXISMOTION:
{
const int value = ev.jaxis.value;
if(user_config->m_gamepad_debug)
{
printf("axis motion: which=%d axis=%d value=%d\n",
ev.jaxis.which, ev.jaxis.axis, value);
}
// FIXME - AD_NEGATIVE/AD_POSITIVE are probably useless since value contains that info too
if(value < 0)
input(Input::IT_STICKMOTION, ev.jaxis.which, ev.jaxis.axis, Input::AD_NEGATIVE, value);
else
input(Input::IT_STICKMOTION, ev.jaxis.which, ev.jaxis.axis, Input::AD_POSITIVE, value);
}
break;
case SDL_JOYBUTTONUP:
// See the SDL_JOYAXISMOTION case label because of !m_mode thingie.
input(Input::IT_STICKBUTTON, ev.jbutton.which,
ev.jbutton.button, 0, 0);
break;
case SDL_JOYBUTTONDOWN:
// See the SDL_JOYAXISMOTION case label because of !m_mode thingie.
input(Input::IT_STICKBUTTON, ev.jbutton.which, ev.jbutton.button, 0, 32768);
break;
*/
}
else if(event.EventType == EET_KEY_INPUT_EVENT)
{

View File

@@ -68,7 +68,7 @@ private:
int m_mouse_val_x, m_mouse_val_y;
void input(Input::InputType, int, int, int, int);
void postIrrLichtMouseEvent(irr::EMOUSE_INPUT_EVENT type, const int x, const int y);
//void postIrrLichtMouseEvent(irr::EMOUSE_INPUT_EVENT type, const int x, const int y);
void handleStaticAction(int id0, int value);
void handlePlayerAction(PlayerAction pa, const int playerNo, int value);
public: