More work towards multiplayer (player 1 is now assigned an input device when pressing 'new game'). Cleanup when restarting game not implemented
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3701 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
1c256c7805
commit
a7abbf4c82
@ -22,11 +22,14 @@
|
||||
|
||||
#include <string>
|
||||
#include "config/user_config.hpp"
|
||||
#include "input/input_device.hpp"
|
||||
|
||||
class InputDevice;
|
||||
|
||||
/**
|
||||
* class for managing player name and control configuration
|
||||
* class for managing player name and control configuration.
|
||||
* A list of all possible players is stored in the user config.
|
||||
* A list of currently playing players will be stored somewhere else (FIXME : complete comment)
|
||||
*/
|
||||
class Player
|
||||
{
|
||||
@ -50,8 +53,12 @@ public:
|
||||
m_device = NULL;
|
||||
}
|
||||
|
||||
InputDevice* getDevice() { return m_device; }
|
||||
void setDevice(InputDevice* device) { m_device = device; }
|
||||
InputDevice* getDevice() const { return m_device; }
|
||||
void setDevice(InputDevice* device)
|
||||
{
|
||||
m_device = device;
|
||||
device->setPlayer(this);
|
||||
}
|
||||
|
||||
void setName(const std::string &name_){m_name = name_;}
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "gui/engine.hpp"
|
||||
#include "gui/screen.hpp"
|
||||
#include "gui/state_manager.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_device.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
@ -84,9 +87,7 @@ namespace StateManager
|
||||
const int modelMaxHeight = area->h - 25 - 65;
|
||||
const int modelMaxWidth = area->w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
|
||||
std::cout << "bestSize=" << bestSize << std::endl;
|
||||
|
||||
|
||||
modelView->x = area->x + area->w/2 - bestSize*1.2/2;
|
||||
modelView->y = modelY + modelMaxHeight/2 - bestSize/2;
|
||||
modelView->w = bestSize*1.2; // FIXME : for some reason, it looks better this way, though full square should be ok
|
||||
@ -117,8 +118,8 @@ namespace StateManager
|
||||
|
||||
};
|
||||
|
||||
// TODO : have one per player
|
||||
PlayerKart* playerKart1 = NULL;
|
||||
// ref only since we're adding them to a Screen, and the Screen will take ownership of these widgets
|
||||
ptr_vector<PlayerKart, REF> g_player_karts;
|
||||
|
||||
class KartHoverListener : public RibbonGridHoverListener
|
||||
{
|
||||
@ -129,7 +130,8 @@ class KartHoverListener : public RibbonGridHoverListener
|
||||
|
||||
if(selectionID.size() == 0) return;
|
||||
|
||||
ModelViewWidget* w3 = playerKart1->modelView;
|
||||
// TODO : support players other than player 0 (i.e. multiplayer)
|
||||
ModelViewWidget* w3 = g_player_karts[0].modelView;
|
||||
assert( w3 != NULL );
|
||||
|
||||
const KartProperties* kart = kart_properties_manager->getKart(selectionID);
|
||||
@ -144,11 +146,38 @@ class KartHoverListener : public RibbonGridHoverListener
|
||||
w3->addModel( kartModel->getWheelModel(3), kartModel->getWheelGraphicsPosition(3) );
|
||||
w3->update(0);
|
||||
|
||||
playerKart1->kartName->setText( kart->getName().c_str() );
|
||||
// TODO : support players other than player 0 (i.e. multiplayer)
|
||||
g_player_karts[0].kartName->setText( kart->getName().c_str() );
|
||||
}
|
||||
};
|
||||
KartHoverListener* karthoverListener = NULL;
|
||||
|
||||
void setPlayer0Device(InputDevice* device)
|
||||
{
|
||||
if(device == NULL)
|
||||
{
|
||||
std::cout << "I don't know which device to assign to player 0 :'(\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if(device->getType() == DT_KEYBOARD)
|
||||
{
|
||||
std::cout << "Player 0 is using a keyboard\n";
|
||||
}
|
||||
if(device->getType() == DT_GAMEPAD)
|
||||
{
|
||||
std::cout << "Player 0 is using a gamepad\n";
|
||||
}
|
||||
|
||||
// TODO : support moer than 1 player
|
||||
StateManager::addActivePlayer( UserConfigParams::m_player.get(0) );
|
||||
UserConfigParams::m_player[0].setDevice(device);
|
||||
|
||||
// TODO : fall back in no-assign mode when aborting a game and going back to the menu
|
||||
input_manager->getDeviceList()->setNoAssignMode(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback handling events from the kart selection menu
|
||||
*/
|
||||
@ -171,9 +200,10 @@ void menuEventKarts(Widget* widget, std::string& name)
|
||||
|
||||
Widget* area = getCurrentScreen()->getWidget("playerskarts");
|
||||
|
||||
playerKart1 = new PlayerKart(area);
|
||||
PlayerKart* playerKart1 = new PlayerKart(area);
|
||||
getCurrentScreen()->manualAddWidget(playerKart1);
|
||||
playerKart1->add();
|
||||
g_player_karts.push_back(playerKart1);
|
||||
|
||||
// Build kart list
|
||||
const int kart_amount = kart_properties_manager->getNumberOfKarts();
|
||||
|
@ -23,8 +23,10 @@ namespace GUIEngine
|
||||
{
|
||||
class Widget;
|
||||
}
|
||||
class InputDevice;
|
||||
|
||||
namespace StateManager
|
||||
{
|
||||
void setPlayer0Device(InputDevice* device);
|
||||
void menuEventKarts(GUIEngine::Widget* widget, std::string& name);
|
||||
}
|
||||
|
@ -89,7 +89,6 @@ void ModalDialog::dismiss()
|
||||
|
||||
void ModalDialog::onEnterPressed()
|
||||
{
|
||||
std::cout << "onEnterPressed()\n";
|
||||
if(modalWindow != NULL) modalWindow->onEnterPressedInternal();
|
||||
}
|
||||
|
||||
@ -263,51 +262,69 @@ void EnterPlayerNameDialog::onEnterPressedInternal()
|
||||
|
||||
TrackInfoDialog::TrackInfoDialog(const char* trackName, ITexture* screenshot, const float w, const float h) : ModalDialog(w, h)
|
||||
{
|
||||
const int y1 = m_area.getHeight()/3;
|
||||
const int y2 = m_area.getHeight() - 50;
|
||||
const int y1 = m_area.getHeight()/7;
|
||||
const int y2 = m_area.getHeight()*5/7;
|
||||
const int y3 = m_area.getHeight()*6/7;
|
||||
|
||||
SpinnerWidget* spinner = new SpinnerWidget();
|
||||
spinner->x = m_area.getWidth()/2 - 200;
|
||||
spinner->y = y2;
|
||||
spinner->w = 400;
|
||||
spinner->h = y3 - y2 - 15;
|
||||
spinner->setParent(m_irrlicht_window);
|
||||
|
||||
spinner->m_properties[PROP_MIN_VALUE] = "1";
|
||||
spinner->m_properties[PROP_MAX_VALUE] = "99";
|
||||
spinner->m_properties[PROP_TEXT] = "%i laps";
|
||||
|
||||
m_children.push_back(spinner);
|
||||
spinner->add();
|
||||
spinner->setValue(3);
|
||||
spinner->m_element->setTabStop(true);
|
||||
spinner->m_element->setTabGroup(false);
|
||||
|
||||
ButtonWidget* okBtn = new ButtonWidget();
|
||||
okBtn->m_properties[PROP_ID] = "start";
|
||||
okBtn->m_properties[PROP_TEXT] = _("Start Race");
|
||||
okBtn->x = m_area.getWidth()/2 - 200;
|
||||
okBtn->y = y3;
|
||||
okBtn->w = 400;
|
||||
okBtn->h = m_area.getHeight() - y3 - 15;
|
||||
okBtn->setParent(m_irrlicht_window);
|
||||
m_children.push_back(okBtn);
|
||||
okBtn->add();
|
||||
okBtn->m_element->setTabStop(true);
|
||||
okBtn->m_element->setTabGroup(false);
|
||||
|
||||
GUIEngine::getGUIEnv()->setFocus( okBtn->m_element );
|
||||
|
||||
|
||||
core::rect< s32 > area_top(0, 0, m_area.getWidth(), y1);
|
||||
IGUIStaticText* a = GUIEngine::getGUIEnv()->addStaticText( stringw(trackName).c_str(),
|
||||
area_top, false /* border */, true /* word wrap */,
|
||||
area_top, false, true, // border, word warp
|
||||
m_irrlicht_window);
|
||||
|
||||
a->setTabStop(false);
|
||||
|
||||
|
||||
core::rect< s32 > area_left(0, y1, m_area.getWidth()/2, y2);
|
||||
IGUIStaticText* b = GUIEngine::getGUIEnv()->addStaticText( stringw(_("High Scores & Track Info")).c_str(),
|
||||
area_left, false /* border */, true /* word wrap */,
|
||||
area_left, false , true , // border, word warp
|
||||
m_irrlicht_window);
|
||||
|
||||
b->setTabStop(false);
|
||||
|
||||
|
||||
// TODO : preserve aspect ratio
|
||||
core::rect< s32 > area_right(m_area.getWidth()/2, y1, m_area.getWidth(), y2);
|
||||
core::rect< s32 > area_right(m_area.getWidth()/2, y1, m_area.getWidth(), y2-10);
|
||||
IGUIImage* screenshotWidget = GUIEngine::getGUIEnv()->addImage( area_right, m_irrlicht_window );
|
||||
screenshotWidget->setImage(screenshot);
|
||||
screenshotWidget->setScaleImage(true);
|
||||
screenshotWidget->setTabStop(false);
|
||||
|
||||
|
||||
SpinnerWidget* widget = new SpinnerWidget();
|
||||
widget->x = 0;
|
||||
widget->y = y2;
|
||||
widget->w = m_area.getWidth();
|
||||
widget->h = m_area.getHeight() - y2;
|
||||
widget->setParent(m_irrlicht_window);
|
||||
|
||||
widget->m_properties[PROP_MIN_VALUE] = "1";
|
||||
widget->m_properties[PROP_MAX_VALUE] = "99";
|
||||
widget->m_properties[PROP_TEXT] = "%i laps";
|
||||
|
||||
m_children.push_back(widget);
|
||||
widget->add();
|
||||
widget->setValue(3);
|
||||
|
||||
//IGUIStaticText* d = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Number of laps")).c_str(),
|
||||
// area_bottom, false /* border */, true /* word wrap */,
|
||||
// m_irrlicht_window);
|
||||
|
||||
|
||||
a->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
|
||||
b->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
|
||||
//d->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
@ -343,7 +360,11 @@ void TrackInfoDialog::onEnterPressedInternal()
|
||||
{
|
||||
startGame();
|
||||
}
|
||||
|
||||
|
||||
void TrackInfoDialog::processEvent(std::string& eventSource)
|
||||
{
|
||||
if (eventSource == "start" ) startGame();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
*/
|
||||
TrackInfoDialog(const char* trackName, irr::video::ITexture* screenshot, const float percentWidth, const float percentHeight);
|
||||
void onEnterPressedInternal();
|
||||
void processEvent(std::string& eventSource);
|
||||
};
|
||||
|
||||
class PlayerInfoDialog : public ModalDialog
|
||||
|
@ -443,17 +443,19 @@ void Screen::processAction(const int action, const unsigned int value, Input::In
|
||||
switch(action)
|
||||
{
|
||||
case PA_LEFT:
|
||||
/*
|
||||
if(type == Input::IT_STICKMOTION)
|
||||
{
|
||||
// simulate a key press
|
||||
irr::SEvent::SKeyInput evt;
|
||||
evt.PressedDown = pressedDown;
|
||||
evt.Key = KEY_LEFT;
|
||||
evt.Key = KEY_LEFT; // FIXME : what if keyboard bindings are not set to use this key?
|
||||
irr::SEvent wrapper;
|
||||
wrapper.KeyInput = evt;
|
||||
wrapper.EventType = EET_KEY_INPUT_EVENT;
|
||||
GUIEngine::getDevice()->postEventFromUser(wrapper);
|
||||
}
|
||||
*/
|
||||
{
|
||||
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
|
||||
if(el == NULL) break;
|
||||
@ -475,17 +477,18 @@ void Screen::processAction(const int action, const unsigned int value, Input::In
|
||||
break;
|
||||
|
||||
case PA_RIGHT:
|
||||
/*
|
||||
if(type == Input::IT_STICKMOTION)
|
||||
{
|
||||
// simulate a key press
|
||||
irr::SEvent::SKeyInput evt;
|
||||
evt.PressedDown = pressedDown;
|
||||
evt.Key = KEY_RIGHT;
|
||||
evt.Key = KEY_RIGHT; // FIXME : what if keyboard bindings are not set to use this key?
|
||||
irr::SEvent wrapper;
|
||||
wrapper.KeyInput = evt;
|
||||
wrapper.EventType = EET_KEY_INPUT_EVENT;
|
||||
GUIEngine::getDevice()->postEventFromUser(wrapper);
|
||||
}
|
||||
}*/
|
||||
{
|
||||
IGUIElement *el = GUIEngine::getGUIEnv()->getFocus();
|
||||
if(el == NULL) break;
|
||||
@ -537,9 +540,10 @@ void Screen::processAction(const int action, const unsigned int value, Input::In
|
||||
if(stay_within_list) break;
|
||||
else list->setSelected(-1);
|
||||
}
|
||||
|
||||
|
||||
// find closest widget
|
||||
if(el != NULL && el->getTabGroup() != NULL &&
|
||||
el->getTabGroup()->getNextElement(el->getTabOrder(), true, false, first, closest))
|
||||
el->getTabGroup()->getNextElement(el->getTabOrder(), true /* reverse */, false /* group */, first, closest))
|
||||
{
|
||||
GUIEngine::getGUIEnv()->setFocus(closest);
|
||||
|
||||
@ -558,6 +562,8 @@ void Screen::processAction(const int action, const unsigned int value, Input::In
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Could not find any!\n";
|
||||
|
||||
// select the first widget
|
||||
Widget* w = getLastWidget();
|
||||
|
||||
@ -622,28 +628,16 @@ void Screen::processAction(const int action, const unsigned int value, Input::In
|
||||
case PA_FIRE:
|
||||
if(type == Input::IT_STICKBUTTON)
|
||||
{
|
||||
// simulate a 'enter' key press. doesn't seem to work
|
||||
// simulate a 'enter' key press
|
||||
irr::SEvent::SKeyInput evt;
|
||||
evt.PressedDown = pressedDown;
|
||||
evt.Key = KEY_SPACE; // KEY_RETURN
|
||||
evt.Key = KEY_SPACE; // FIXME : what if keyboard bindings are not set to use this key?
|
||||
evt.Char = 666; // My magic code to know it's a fake event (FIXME : ugly, but irrlicht doesn't seem to offer better)
|
||||
irr::SEvent wrapper;
|
||||
wrapper.KeyInput = evt;
|
||||
|
||||
wrapper.EventType = EET_KEY_INPUT_EVENT;
|
||||
GUIEngine::getDevice()->postEventFromUser(wrapper);
|
||||
|
||||
/*
|
||||
irr::SEvent::SGUIEvent evt;
|
||||
evt.EventType = EGET_BUTTON_CLICKED;
|
||||
evt.Element = GUIEngine::getGUIEnv()->getFocus();
|
||||
evt.Caller = GUIEngine::getGUIEnv()->getFocus();
|
||||
irr::SEvent wrapper;
|
||||
wrapper.GUIEvent = evt;
|
||||
wrapper.EventType = EET_GUI_EVENT;
|
||||
// GUIEngine::getDevice()->postEventFromUser(wrapper);
|
||||
this->OnEvent(wrapper);
|
||||
// std::cout << "posting event to simulate 'enter'\n";
|
||||
*/
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -41,20 +41,35 @@
|
||||
|
||||
using namespace GUIEngine;
|
||||
|
||||
/**
|
||||
* This stack will contain menu names (e.g. main.stkgui), and/or 'race'.
|
||||
*/
|
||||
std::vector<std::string> g_menu_stack;
|
||||
|
||||
static bool g_game_mode = false;
|
||||
namespace StateManager
|
||||
{
|
||||
static bool g_game_mode = false;
|
||||
|
||||
/**
|
||||
* This stack will contain menu names (e.g. main.stkgui), and/or 'race'.
|
||||
*/
|
||||
std::vector<std::string> g_menu_stack;
|
||||
|
||||
/**
|
||||
* A list of all currently playing players. (only storing references since
|
||||
* the original is in UserConfig)
|
||||
*/
|
||||
ptr_vector<Player, REF> g_active_players;
|
||||
|
||||
const ptr_vector<Player, REF>& getActivePlayers()
|
||||
{
|
||||
return g_active_players;
|
||||
}
|
||||
void addActivePlayer(Player* p)
|
||||
{
|
||||
g_active_players.push_back(p);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark Callbacks
|
||||
#endif
|
||||
|
||||
namespace StateManager
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/**
|
||||
* Callback handling events from the main menu
|
||||
@ -68,6 +83,8 @@ namespace StateManager
|
||||
|
||||
if(selection == "new")
|
||||
{
|
||||
InputDevice* device = input_manager->getDeviceList()->getLatestUsedDevice();
|
||||
StateManager::setPlayer0Device(device);
|
||||
StateManager::pushMenu("karts.stkgui");
|
||||
}
|
||||
else if(selection == "options")
|
||||
@ -239,7 +256,7 @@ namespace StateManager
|
||||
|
||||
ITexture* screenshot = GUIEngine::getDriver()->getTexture( (file_manager->getDataDir() + "/gui/track1.png").c_str() );
|
||||
|
||||
new TrackInfoDialog( w2->getSelectionText().c_str(), screenshot, 0.75f, 0.6f);
|
||||
new TrackInfoDialog( w2->getSelectionText().c_str(), screenshot, 0.8f, 0.7f);
|
||||
}
|
||||
}
|
||||
else if(name == "gps")
|
||||
|
@ -20,8 +20,10 @@
|
||||
#define STATE_MANAGER_HPP
|
||||
|
||||
#include <string>
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
struct Input;
|
||||
class Player;
|
||||
|
||||
namespace StateManager
|
||||
{
|
||||
@ -35,6 +37,9 @@ namespace StateManager
|
||||
bool isGameState();
|
||||
void reshowTopMostMenu();
|
||||
|
||||
const ptr_vector<Player, REF>& getActivePlayers();
|
||||
void addActivePlayer(Player* p);
|
||||
|
||||
void escapePressed();
|
||||
}
|
||||
|
||||
|
@ -768,6 +768,8 @@ void SpinnerWidget::add()
|
||||
rect<s32> widget_size = rect<s32>(x, y, x + w, y + h);
|
||||
IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, L"");
|
||||
m_element = btn;
|
||||
|
||||
m_element->setTabOrder( m_element->getID() );
|
||||
|
||||
// left arrow
|
||||
rect<s32> subsize_left_arrow = rect<s32>(0 ,0, h, h);
|
||||
|
@ -3,14 +3,18 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "config/player.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "gui/state_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
DeviceManager::DeviceManager()
|
||||
{
|
||||
m_keyboard_amount = 0;
|
||||
m_gamepad_amount = 0;
|
||||
m_latest_used_device = NULL;
|
||||
m_no_assign_mode = true;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
bool DeviceManager::initGamePadSupport()
|
||||
@ -40,6 +44,11 @@ bool DeviceManager::initGamePadSupport()
|
||||
return something_new_to_write;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DeviceManager::setNoAssignMode(const bool noAssignMode)
|
||||
{
|
||||
m_no_assign_mode = noAssignMode;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
|
||||
{
|
||||
for(unsigned int i=0; i<m_gamepad_amount; i++)
|
||||
@ -91,16 +100,53 @@ void DeviceManager::add(GamePadDevice* d)
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int deviceID, int btnID, int axisDir, int value,
|
||||
int* player /* out */, PlayerAction* action /* out */ )
|
||||
const bool programaticallyGenerated, int* player /* out */,
|
||||
PlayerAction* action /* out */ )
|
||||
{
|
||||
// TODO - auto-detect player ID from device
|
||||
*player = 0;
|
||||
if(m_no_assign_mode)
|
||||
{
|
||||
*player = -1;
|
||||
}
|
||||
|
||||
|
||||
if(type == Input::IT_KEYBOARD)
|
||||
{
|
||||
for(unsigned int n=0; n<m_keyboard_amount; n++)
|
||||
{
|
||||
if( m_keyboards[n].hasBinding(btnID, action) ) return true;
|
||||
if( m_keyboards[n].hasBinding(btnID, action) )
|
||||
{
|
||||
// We found which device was triggered.
|
||||
|
||||
if(m_no_assign_mode)
|
||||
{
|
||||
// In no-assign mode, simply keep track of which device is used
|
||||
if(!programaticallyGenerated) m_latest_used_device = m_keyboards.get(n);
|
||||
|
||||
//if(programaticallyGenerated) std::cout << "devieManager ignores programatical event\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// In assign mode, find to which active player this binding belongs
|
||||
// FIXME : in order to speed this use, a Player* pointer could be
|
||||
// stored inside the device so we don't need to iterate through devices
|
||||
const ptr_vector<Player, REF>& players = StateManager::getActivePlayers();
|
||||
const int playerAmount = players.size();
|
||||
for(int n=0; n<playerAmount; n++)
|
||||
{
|
||||
if(players[n].getDevice() == m_keyboards.get(n))
|
||||
{
|
||||
// we found which active player has this binding
|
||||
*player = n;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// no active player has this binding
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -110,16 +156,33 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
|
||||
}
|
||||
else if(type == Input::IT_STICKBUTTON || type == Input::IT_STICKMOTION)
|
||||
{
|
||||
for(unsigned int n=0; n<m_gamepad_amount; n++)
|
||||
|
||||
GamePadDevice* gamepad = getGamePadFromIrrID(deviceID);
|
||||
|
||||
if(m_no_assign_mode)
|
||||
{
|
||||
//std::cout << "checking gamepad #" << n << " out of " << m_gamepad_amount << std::endl;
|
||||
// In no-assign mode, simply keep track of which device is used
|
||||
if(!programaticallyGenerated)
|
||||
m_latest_used_device = gamepad;
|
||||
|
||||
if(m_gamepads[n].hasBinding(type, btnID /* axis or button */, value, *player, action /* out */) )
|
||||
if(gamepad->hasBinding(type, btnID /* axis or button */, value, *player, action /* out */) )
|
||||
{
|
||||
//std::cout << "that's the one.\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(gamepad->m_player_id != -1)
|
||||
*player = gamepad->m_player_id;
|
||||
else
|
||||
return false; // no player mapped to this device
|
||||
|
||||
if(gamepad->hasBinding(type, btnID /* axis or button */, value, *player, action /* out */) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@ -130,6 +193,14 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
|
||||
return false;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
InputDevice* DeviceManager::getLatestUsedDevice()
|
||||
{
|
||||
// If none, probably the user clicked or used enter; give keyboard by default
|
||||
if (m_latest_used_device == NULL ) return m_keyboards.get(0);
|
||||
|
||||
return m_latest_used_device;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
bool DeviceManager::deserialize()
|
||||
{
|
||||
static std::string filepath = file_manager->getHomeDir() + "/input.config";
|
||||
|
@ -14,6 +14,10 @@ class DeviceManager
|
||||
unsigned int m_keyboard_amount;
|
||||
unsigned int m_gamepad_amount;
|
||||
|
||||
InputDevice* m_latest_used_device;
|
||||
|
||||
bool m_no_assign_mode;
|
||||
|
||||
public:
|
||||
DeviceManager();
|
||||
|
||||
@ -23,13 +27,21 @@ public:
|
||||
int getGamePadAmount() const { return m_gamepad_amount; }
|
||||
GamePadDevice* getGamePad(const int i) { return m_gamepads.get(i); }
|
||||
GamePadDevice* getGamePadFromIrrID(const int i);
|
||||
InputDevice* getLatestUsedDevice();
|
||||
|
||||
/**
|
||||
* The device manager starts in "no-assign" mode, which means no input configuration is associated
|
||||
* to any player. So all devices will react. This is used in menus before player set-up is done.
|
||||
*/
|
||||
bool noAssignMode() const { return m_no_assign_mode; }
|
||||
void setNoAssignMode(const bool noAssignMode);
|
||||
|
||||
int getKeyboardAmount() const { return m_keyboard_amount; }
|
||||
KeyboardDevice* getKeyboard(const int i) { return m_keyboards.get(i); }
|
||||
|
||||
/** Given some input, finds to which device it belongs and, using the corresponding device object,
|
||||
maps this input to the corresponding player and game action. returns false if player/action could not be set */
|
||||
bool mapInputToPlayerAndAction( Input::InputType type, int id0, int id1, int id2, int value,
|
||||
bool mapInputToPlayerAndAction( Input::InputType type, int id0, int id1, int id2, int value, const bool programaticallyGenerated,
|
||||
int* player /* out */, PlayerAction* action /* out */ );
|
||||
|
||||
void serialize();
|
||||
|
@ -11,8 +11,24 @@ InputDevice::InputDevice()
|
||||
{
|
||||
m_default_bindings[n].id = -1;
|
||||
m_default_bindings[n].type = Input::IT_NONE;
|
||||
m_default_bindings[n].dir = Input::AD_NEGATIVE;
|
||||
m_default_bindings[n].dir = Input::AD_NEUTRAL;
|
||||
}
|
||||
m_player_id = -1;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void InputDevice::setPlayer(Player* owner)
|
||||
{
|
||||
const ptr_vector<Player, REF>& players = StateManager::getActivePlayers();
|
||||
const int playerAmount = players.size();
|
||||
for(int n=0; n<playerAmount; n++)
|
||||
{
|
||||
if(players.getConst(n) == owner)
|
||||
{
|
||||
m_player_id = n; // TODO : reset m_player_id when ending a game
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::cerr << "Error, trying to assign that doesn't exist to a device\n";
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void InputDevice::serialize(std::ofstream& stream)
|
||||
@ -295,7 +311,8 @@ void GamePadDevice::resetAxisDirection(const int axis, Input::AxisDirection dire
|
||||
bool GamePadDevice::hasBinding(Input::InputType type, const int id, const int value, const int player, PlayerAction* action /* out */)
|
||||
{
|
||||
if(m_prevAxisDirections == NULL) return false; // device not open
|
||||
|
||||
//if(player != m_player_id && player != -1) return false; // device open, but belongs to another player
|
||||
|
||||
if(type == Input::IT_STICKMOTION)
|
||||
{
|
||||
if(id >= m_axis_count) return false; // this gamepad doesn't even have that many axes
|
||||
@ -305,7 +322,6 @@ bool GamePadDevice::hasBinding(Input::InputType type, const int id, const int va
|
||||
{
|
||||
// set positive id to 0
|
||||
resetAxisDirection(id, Input::AD_POSITIVE, player);
|
||||
|
||||
}
|
||||
// going to positive from negative
|
||||
else if (value > 0 && m_prevAxisDirections[id] == Input::AD_NEGATIVE)
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <fstream>
|
||||
#include "io/xml_node.hpp"
|
||||
|
||||
class Player;
|
||||
|
||||
enum DeviceType
|
||||
{
|
||||
DT_KEYBOARD,
|
||||
@ -25,11 +27,13 @@ struct KeyBinding
|
||||
|
||||
class InputDevice
|
||||
{
|
||||
friend class DeviceManager;
|
||||
protected:
|
||||
DeviceType m_type;
|
||||
KeyBinding m_default_bindings[PA_COUNT];
|
||||
|
||||
|
||||
int m_player_id;
|
||||
|
||||
public:
|
||||
std::string m_name; // if device has a name; unused for keyboards since AFAIK we can't tell keyboards apart
|
||||
|
||||
@ -37,6 +41,8 @@ public:
|
||||
|
||||
DeviceType getType() const { return m_type; };
|
||||
|
||||
void setPlayer(Player* owner);
|
||||
|
||||
/**
|
||||
* returns a human-readable string for the key binded with the given action
|
||||
*/
|
||||
|
@ -251,16 +251,18 @@ void InputManager::inputSensing(Input::InputType type, int deviceID, int btnID,
|
||||
* Note: It is the obligation of the called menu to switch of the sense mode.
|
||||
*
|
||||
*/
|
||||
void InputManager::input(Input::InputType type, int deviceID, int btnID, int axisDirection, int value)
|
||||
void InputManager::input(Input::InputType type, int deviceID, int btnID, int axisDirection, int value,
|
||||
const bool programaticallyGenerated)
|
||||
{
|
||||
int player;
|
||||
PlayerAction action;
|
||||
|
||||
bool action_found = m_device_manager->mapInputToPlayerAndAction( type, deviceID, btnID, axisDirection, value, &player, &action );
|
||||
bool action_found = m_device_manager->mapInputToPlayerAndAction( type, deviceID, btnID, axisDirection,
|
||||
value, programaticallyGenerated, &player, &action );
|
||||
|
||||
|
||||
// in menus, some keyboard keys are standard
|
||||
if(!StateManager::isGameState() && type == Input::IT_KEYBOARD && m_mode == MENU)
|
||||
// in menus, some keyboard keys are standard (before each player selected his device)
|
||||
// FIXME: should enter always work to accept for a player using keyboard?
|
||||
if(!StateManager::isGameState() && type == Input::IT_KEYBOARD && m_mode == MENU && m_device_manager->noAssignMode())
|
||||
{
|
||||
action = PA_FIRST;
|
||||
|
||||
@ -339,6 +341,9 @@ void InputManager::input(Input::InputType type, int deviceID, int btnID, int axi
|
||||
bool InputManager::input(const SEvent& event)
|
||||
{
|
||||
|
||||
//const bool programaticallyGenerated = (event.UserEvent.UserData1 == 666 && event.UserEvent.UserData1 == 999);
|
||||
const bool programaticallyGenerated = event.EventType == EET_KEY_INPUT_EVENT && (event.KeyInput.Char == 666);
|
||||
|
||||
if(event.EventType == EET_JOYSTICK_INPUT_EVENT)
|
||||
{
|
||||
// Axes - FIXME, instead of checking all of them, ask the bindings which ones to poll
|
||||
@ -359,9 +364,9 @@ bool InputManager::input(const SEvent& event)
|
||||
|
||||
// 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);
|
||||
input(Input::IT_STICKMOTION, event.JoystickEvent.Joystick , axis_id, Input::AD_NEGATIVE, value, programaticallyGenerated);
|
||||
else
|
||||
input(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, axis_id, Input::AD_POSITIVE, value);
|
||||
input(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, axis_id, Input::AD_POSITIVE, value, programaticallyGenerated);
|
||||
}
|
||||
|
||||
GamePadDevice* gp = getDeviceList()->getGamePadFromIrrID(event.JoystickEvent.Joystick);
|
||||
@ -371,7 +376,7 @@ bool InputManager::input(const SEvent& event)
|
||||
const bool isButtonPressed = event.JoystickEvent.IsButtonPressed(i);
|
||||
|
||||
if(gp->isButtonPressed(i) || isButtonPressed)
|
||||
input(Input::IT_STICKBUTTON, event.JoystickEvent.Joystick, i, 0, isButtonPressed ? MAX_VALUE : 0);
|
||||
input(Input::IT_STICKBUTTON, event.JoystickEvent.Joystick, i, 0, isButtonPressed ? MAX_VALUE : 0, programaticallyGenerated);
|
||||
gp->setButtonPressed(i, isButtonPressed);
|
||||
}
|
||||
|
||||
@ -413,12 +418,12 @@ bool InputManager::input(const SEvent& event)
|
||||
#else
|
||||
ev.key.keysym.unicode,
|
||||
#endif
|
||||
MAX_VALUE);
|
||||
MAX_VALUE, programaticallyGenerated);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
input(Input::IT_KEYBOARD, 0, key, 0, 0);
|
||||
input(Input::IT_KEYBOARD, 0, key, 0, 0, programaticallyGenerated);
|
||||
}
|
||||
}
|
||||
#if 0 // in case we ever use mouse in-game...
|
||||
|
@ -67,7 +67,7 @@ private:
|
||||
*/
|
||||
int m_mouse_val_x, m_mouse_val_y;
|
||||
|
||||
void input(Input::InputType, int, int, int, int);
|
||||
void input(Input::InputType, int, int, int, int, const bool programaticallyGenerated);
|
||||
void handleStaticAction(int id0, int value);
|
||||
void handlePlayerAction(PlayerAction pa, const int playerNo, int value);
|
||||
void inputSensing(Input::InputType type, int deviceID, int btnID, int axisDirection, int value);
|
||||
|
@ -128,6 +128,15 @@ TYPE* get(const int ID)
|
||||
return contentsVector[ID];
|
||||
}
|
||||
|
||||
const TYPE* getConst(const int ID) const
|
||||
{
|
||||
|
||||
assert(ID > -1);
|
||||
assert((unsigned int)ID < contentsVector.size());
|
||||
|
||||
return contentsVector[ID];
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return contentsVector.size();
|
||||
|
Loading…
Reference in New Issue
Block a user