You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
934 lines
28 KiB
C++
934 lines
28 KiB
C++
/* -------------------------------------------------------
|
|
Copyright (c) 2011 Alberto G. Salguero (alberto.salguero (at) uca.es)
|
|
|
|
Permission is hereby granted, free of charge, to any
|
|
person obtaining a copy of this software and associated
|
|
documentation files (the "Software"), to deal in the
|
|
Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the
|
|
Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice
|
|
shall be included in all copies or substantial portions of
|
|
the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
------------------------------------------------------- */
|
|
|
|
#include "ICSInputControlSystem.h"
|
|
|
|
namespace ICS
|
|
{
|
|
InputControlSystem::InputControlSystem(std::string file, bool active
|
|
, DetectingBindingListener* detectingBindingListener
|
|
, InputControlSystemLog* log, size_t channelCount)
|
|
: mFileName(file)
|
|
, mDetectingBindingListener(detectingBindingListener)
|
|
, mDetectingBindingControl(NULL)
|
|
, mLog(log)
|
|
, mXmouseAxisBinded(false), mYmouseAxisBinded(false)
|
|
{
|
|
ICS_LOG(" - Creating InputControlSystem - ");
|
|
|
|
this->mActive = active;
|
|
|
|
this->fillSDLKeysMap();
|
|
|
|
ICS_LOG("Channel count = " + ToString<size_t>(channelCount) );
|
|
for(size_t i=0;i<channelCount;i++)
|
|
{
|
|
mChannels.push_back(new Channel((int)i));
|
|
}
|
|
|
|
if(file != "")
|
|
{
|
|
TiXmlDocument* xmlDoc;
|
|
TiXmlElement* xmlRoot;
|
|
|
|
ICS_LOG("Loading file \""+file+"\"");
|
|
|
|
xmlDoc = new TiXmlDocument(file.c_str());
|
|
xmlDoc->LoadFile();
|
|
|
|
if(xmlDoc->Error())
|
|
{
|
|
std::ostringstream message;
|
|
message << "TinyXml reported an error reading \""+ file + "\". Row " <<
|
|
(int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " <<
|
|
xmlDoc->ErrorDesc() ;
|
|
ICS_LOG(message.str());
|
|
|
|
delete xmlDoc;
|
|
return;
|
|
}
|
|
|
|
xmlRoot = xmlDoc->RootElement();
|
|
if(std::string(xmlRoot->Value()) != "Controller") {
|
|
ICS_LOG("Error: Invalid Controller file. Missing <Controller> element.");
|
|
delete xmlDoc;
|
|
return;
|
|
}
|
|
|
|
TiXmlElement* xmlControl = xmlRoot->FirstChildElement("Control");
|
|
|
|
size_t controlChannelCount = 0;
|
|
while(xmlControl)
|
|
{
|
|
TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel");
|
|
while(xmlChannel)
|
|
{
|
|
controlChannelCount = std::max(channelCount, FromString<size_t>(xmlChannel->Attribute("number")));
|
|
|
|
xmlChannel = xmlChannel->NextSiblingElement("Channel");
|
|
}
|
|
|
|
xmlControl = xmlControl->NextSiblingElement("Control");
|
|
}
|
|
|
|
if(controlChannelCount > channelCount)
|
|
{
|
|
size_t dif = controlChannelCount - channelCount;
|
|
ICS_LOG("Warning: default channel count exceeded. Adding " + ToString<size_t>(dif) + " channels" );
|
|
for(size_t i = channelCount ; i < controlChannelCount ; i++)
|
|
{
|
|
mChannels.push_back(new Channel((int)i));
|
|
}
|
|
}
|
|
|
|
ICS_LOG("Applying filters to channels");
|
|
//<ChannelFilter number="0">
|
|
// <interval type="bezier" startX="0.0" startY="0.0" midX="0.25" midY="0.5" endX="0.5" endY="0.5" step="0.1" />
|
|
// <interval type="bezier" startX="0.5" startY="0.5" midX="0.75" midY="0.5" endX="1.0" endY="1.0" step="0.1" />
|
|
//</ChannelFilter>
|
|
|
|
TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter");
|
|
while(xmlChannelFilter)
|
|
{
|
|
int ch = FromString<int>(xmlChannelFilter->Attribute("number"));
|
|
|
|
TiXmlElement* xmlInterval = xmlChannelFilter->FirstChildElement("Interval");
|
|
while(xmlInterval)
|
|
{
|
|
std::string type = xmlInterval->Attribute("type");
|
|
|
|
if(type == "bezier")
|
|
{
|
|
float step = 0.1;
|
|
|
|
float startX = FromString<float>(xmlInterval->Attribute("startX"));
|
|
float startY = FromString<float>(xmlInterval->Attribute("startY"));
|
|
float midX = FromString<float>(xmlInterval->Attribute("midX"));
|
|
float midY = FromString<float>(xmlInterval->Attribute("midY"));
|
|
float endX = FromString<float>(xmlInterval->Attribute("endX"));
|
|
float endY = FromString<float>(xmlInterval->Attribute("endY"));
|
|
|
|
step = FromString<float>(xmlInterval->Attribute("step"));
|
|
|
|
ICS_LOG("Applying Bezier filter to channel [number="
|
|
+ ToString<int>(ch) + ", startX="
|
|
+ ToString<float>(startX) + ", startY="
|
|
+ ToString<float>(startY) + ", midX="
|
|
+ ToString<float>(midX) + ", midY="
|
|
+ ToString<float>(midY) + ", endX="
|
|
+ ToString<float>(endX) + ", endY="
|
|
+ ToString<float>(endY) + ", step="
|
|
+ ToString<float>(step) + "]");
|
|
|
|
mChannels.at(ch)->addBezierInterval(startX, startY, midX, midY, endX, endY, step);
|
|
}
|
|
|
|
xmlInterval = xmlInterval->NextSiblingElement("Interval");
|
|
}
|
|
|
|
|
|
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
|
|
}
|
|
|
|
xmlControl = xmlRoot->FirstChildElement("Control");
|
|
while(xmlControl)
|
|
{
|
|
bool axisBindable = true;
|
|
if(xmlControl->Attribute("axisBindable"))
|
|
{
|
|
axisBindable = (std::string( xmlControl->Attribute("axisBindable") ) == "true");
|
|
}
|
|
|
|
ICS_LOG("Adding Control [name="
|
|
+ std::string( xmlControl->Attribute("name") ) + ", autoChangeDirectionOnLimitsAfterStop="
|
|
+ std::string( xmlControl->Attribute("autoChangeDirectionOnLimitsAfterStop") ) + ", autoReverseToInitialValue="
|
|
+ std::string( xmlControl->Attribute("autoReverseToInitialValue") ) + ", initialValue="
|
|
+ std::string( xmlControl->Attribute("initialValue") ) + ", stepSize="
|
|
+ std::string( xmlControl->Attribute("stepSize") ) + ", stepsPerSeconds="
|
|
+ std::string( xmlControl->Attribute("stepsPerSeconds") ) + ", axisBindable="
|
|
+ std::string( (axisBindable)? "true" : "false" ) + "]");
|
|
|
|
float _stepSize = 0;
|
|
if(xmlControl->Attribute("stepSize"))
|
|
{
|
|
std::string value(xmlControl->Attribute("stepSize"));
|
|
if(value == "MAX")
|
|
{
|
|
_stepSize = ICS_MAX;
|
|
}
|
|
else
|
|
{
|
|
_stepSize = FromString<float>(value.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICS_LOG("Warning: no stepSize value found. Default value is 0.");
|
|
}
|
|
|
|
float _stepsPerSeconds = 0;
|
|
if(xmlControl->Attribute("stepsPerSeconds"))
|
|
{
|
|
std::string value(xmlControl->Attribute("stepsPerSeconds"));
|
|
if(value == "MAX")
|
|
{
|
|
_stepsPerSeconds = ICS_MAX;
|
|
}
|
|
else
|
|
{
|
|
_stepsPerSeconds = FromString<float>(value.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICS_LOG("Warning: no stepSize value found. Default value is 0.");
|
|
}
|
|
|
|
addControl( new Control(xmlControl->Attribute("name")
|
|
, std::string( xmlControl->Attribute("autoChangeDirectionOnLimitsAfterStop") ) == "true"
|
|
, std::string( xmlControl->Attribute("autoReverseToInitialValue") ) == "true"
|
|
, FromString<float>(xmlControl->Attribute("initialValue"))
|
|
, _stepSize
|
|
, _stepsPerSeconds
|
|
, axisBindable) );
|
|
|
|
loadKeyBinders(xmlControl);
|
|
|
|
loadMouseAxisBinders(xmlControl);
|
|
|
|
loadMouseButtonBinders(xmlControl);
|
|
|
|
loadJoystickAxisBinders(xmlControl);
|
|
|
|
loadJoystickButtonBinders(xmlControl);
|
|
|
|
loadJoystickPOVBinders(xmlControl);
|
|
|
|
loadJoystickSliderBinders(xmlControl);
|
|
|
|
// Attach controls to channels
|
|
TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel");
|
|
while(xmlChannel)
|
|
{
|
|
ICS_LOG("\tAttaching control to channel [number="
|
|
+ std::string( xmlChannel->Attribute("number") ) + ", direction="
|
|
+ std::string( xmlChannel->Attribute("direction") ) + "]");
|
|
|
|
float percentage = 1;
|
|
if(xmlChannel->Attribute("percentage"))
|
|
{
|
|
if(StringIsNumber<float>(xmlChannel->Attribute("percentage")))
|
|
{
|
|
float val = FromString<float>(xmlChannel->Attribute("percentage"));
|
|
if(val > 1 || val < 0)
|
|
{
|
|
ICS_LOG("ERROR: attaching percentage value range is [0,1]");
|
|
}
|
|
else
|
|
{
|
|
percentage = val;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICS_LOG("ERROR: attaching percentage value range is [0,1]");
|
|
}
|
|
}
|
|
|
|
int chNumber = FromString<int>(xmlChannel->Attribute("number"));
|
|
if(std::string(xmlChannel->Attribute("direction")) == "DIRECT")
|
|
{
|
|
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::DIRECT, percentage);
|
|
}
|
|
else if(std::string(xmlChannel->Attribute("direction")) == "INVERSE")
|
|
{
|
|
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::INVERSE, percentage);
|
|
}
|
|
|
|
xmlChannel = xmlChannel->NextSiblingElement("Channel");
|
|
}
|
|
|
|
xmlControl = xmlControl->NextSiblingElement("Control");
|
|
}
|
|
|
|
std::vector<Channel *>::const_iterator o;
|
|
for(o = mChannels.begin(); o != mChannels.end(); ++o)
|
|
{
|
|
(*o)->update();
|
|
}
|
|
|
|
delete xmlDoc;
|
|
}
|
|
|
|
ICS_LOG(" - InputControlSystem Created - ");
|
|
}
|
|
|
|
InputControlSystem::~InputControlSystem()
|
|
{
|
|
ICS_LOG(" - Deleting InputControlSystem (" + mFileName + ") - ");
|
|
|
|
mJoystickIDList.clear();
|
|
|
|
std::vector<Channel *>::const_iterator o;
|
|
for(o = mChannels.begin(); o != mChannels.end(); ++o)
|
|
{
|
|
delete (*o);
|
|
}
|
|
mChannels.clear();
|
|
|
|
std::vector<Control *>::const_iterator o2;
|
|
for(o2 = mControls.begin(); o2 != mControls.end(); ++o2)
|
|
{
|
|
delete (*o2);
|
|
}
|
|
mControls.clear();
|
|
|
|
mControlsKeyBinderMap.clear();
|
|
mControlsMouseButtonBinderMap.clear();
|
|
mControlsJoystickButtonBinderMap.clear();
|
|
|
|
mKeys.clear();
|
|
mKeyCodes.clear();
|
|
|
|
ICS_LOG(" - InputControlSystem deleted - ");
|
|
}
|
|
|
|
std::string InputControlSystem::getBaseFileName()
|
|
{
|
|
size_t found = mFileName.find_last_of("/\\");
|
|
std::string file = mFileName.substr(found+1);
|
|
|
|
return file.substr(0, file.find_last_of("."));
|
|
}
|
|
|
|
bool InputControlSystem::save(std::string fileName)
|
|
{
|
|
if(fileName != "")
|
|
{
|
|
mFileName = fileName;
|
|
}
|
|
|
|
TiXmlDocument doc( mFileName.c_str() );
|
|
|
|
TiXmlDeclaration dec;
|
|
dec.Parse( "<?xml version='1.0' encoding='utf-8'?>", 0, TIXML_ENCODING_UNKNOWN );
|
|
doc.InsertEndChild(dec);
|
|
|
|
TiXmlElement Controller( "Controller" );
|
|
|
|
for(std::vector<Channel*>::const_iterator o = mChannels.begin() ; o != mChannels.end(); o++)
|
|
{
|
|
ICS::IntervalList intervals = (*o)->getIntervals();
|
|
|
|
if(intervals.size() > 1) // all channels have a default linear filter
|
|
{
|
|
TiXmlElement ChannelFilter( "ChannelFilter" );
|
|
|
|
ChannelFilter.SetAttribute("number", ToString<int>((*o)->getNumber()).c_str());
|
|
|
|
ICS::IntervalList::const_iterator interval = intervals.begin();
|
|
while( interval != intervals.end() )
|
|
{
|
|
// if not default linear filter
|
|
if(!( interval->step == 0.2f
|
|
&& interval->startX == 0.0f
|
|
&& interval->startY == 0.0f
|
|
&& interval->midX == 0.5f
|
|
&& interval->midY == 0.5f
|
|
&& interval->endX == 1.0f
|
|
&& interval->endY == 1.0f ))
|
|
{
|
|
TiXmlElement XMLInterval( "Interval" );
|
|
|
|
XMLInterval.SetAttribute("type", "bezier");
|
|
XMLInterval.SetAttribute("step", ToString<float>(interval->step).c_str());
|
|
|
|
XMLInterval.SetAttribute("startX", ToString<float>(interval->startX).c_str());
|
|
XMLInterval.SetAttribute("startY", ToString<float>(interval->startY).c_str());
|
|
XMLInterval.SetAttribute("midX", ToString<float>(interval->midX).c_str());
|
|
XMLInterval.SetAttribute("midY", ToString<float>(interval->midY).c_str());
|
|
XMLInterval.SetAttribute("endX", ToString<float>(interval->endX).c_str());
|
|
XMLInterval.SetAttribute("endY", ToString<float>(interval->endY).c_str());
|
|
|
|
ChannelFilter.InsertEndChild(XMLInterval);
|
|
}
|
|
|
|
interval++;
|
|
}
|
|
|
|
Controller.InsertEndChild(ChannelFilter);
|
|
}
|
|
}
|
|
|
|
for(std::vector<Control*>::const_iterator o = mControls.begin() ; o != mControls.end(); o++)
|
|
{
|
|
TiXmlElement control( "Control" );
|
|
|
|
control.SetAttribute( "name", (*o)->getName().c_str() );
|
|
if((*o)->getAutoChangeDirectionOnLimitsAfterStop())
|
|
{
|
|
control.SetAttribute( "autoChangeDirectionOnLimitsAfterStop", "true" );
|
|
}
|
|
else
|
|
{
|
|
control.SetAttribute( "autoChangeDirectionOnLimitsAfterStop", "false" );
|
|
}
|
|
if((*o)->getAutoReverse())
|
|
{
|
|
control.SetAttribute( "autoReverseToInitialValue", "true" );
|
|
}
|
|
else
|
|
{
|
|
control.SetAttribute( "autoReverseToInitialValue", "false" );
|
|
}
|
|
control.SetAttribute( "initialValue", ToString<float>((*o)->getInitialValue()).c_str() );
|
|
|
|
if((*o)->getStepSize() == ICS_MAX)
|
|
{
|
|
control.SetAttribute( "stepSize", "MAX" );
|
|
}
|
|
else
|
|
{
|
|
control.SetAttribute( "stepSize", ToString<float>((*o)->getStepSize()).c_str() );
|
|
}
|
|
|
|
if((*o)->getStepsPerSeconds() == ICS_MAX)
|
|
{
|
|
control.SetAttribute( "stepsPerSeconds", "MAX" );
|
|
}
|
|
else
|
|
{
|
|
control.SetAttribute( "stepsPerSeconds", ToString<float>((*o)->getStepsPerSeconds()).c_str() );
|
|
}
|
|
|
|
if(!(*o)->isAxisBindable())
|
|
{
|
|
control.SetAttribute( "axisBindable", "false" );
|
|
}
|
|
|
|
if(getKeyBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) != SDLK_UNKNOWN)
|
|
{
|
|
TiXmlElement keyBinder( "KeyBinder" );
|
|
|
|
keyBinder.SetAttribute( "key", keyCodeToString(
|
|
getKeyBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
|
|
keyBinder.SetAttribute( "direction", "INCREASE" );
|
|
control.InsertEndChild(keyBinder);
|
|
}
|
|
|
|
if(getKeyBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) != SDLK_UNKNOWN)
|
|
{
|
|
TiXmlElement keyBinder( "KeyBinder" );
|
|
|
|
keyBinder.SetAttribute( "key", keyCodeToString(
|
|
getKeyBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
|
|
keyBinder.SetAttribute( "direction", "DECREASE" );
|
|
control.InsertEndChild(keyBinder);
|
|
}
|
|
|
|
if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
|
|
!= InputControlSystem/*::NamedAxis*/::UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "MouseBinder" );
|
|
|
|
InputControlSystem::NamedAxis axis =
|
|
getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE);
|
|
if(axis == InputControlSystem/*::NamedAxis*/::X)
|
|
{
|
|
binder.SetAttribute( "axis", "X" );
|
|
}
|
|
else if(axis == InputControlSystem/*::NamedAxis*/::Y)
|
|
{
|
|
binder.SetAttribute( "axis", "Y" );
|
|
}
|
|
else if(axis == InputControlSystem/*::NamedAxis*/::Z)
|
|
{
|
|
binder.SetAttribute( "axis", "Z" );
|
|
}
|
|
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
|
|
!= InputControlSystem/*::NamedAxis*/::UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "MouseBinder" );
|
|
|
|
InputControlSystem::NamedAxis axis =
|
|
getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE);
|
|
if(axis == InputControlSystem/*::NamedAxis*/::X)
|
|
{
|
|
binder.SetAttribute( "axis", "X" );
|
|
}
|
|
else if(axis == InputControlSystem/*::NamedAxis*/::Y)
|
|
{
|
|
binder.SetAttribute( "axis", "Y" );
|
|
}
|
|
else if(axis == InputControlSystem/*::NamedAxis*/::Z)
|
|
{
|
|
binder.SetAttribute( "axis", "Z" );
|
|
}
|
|
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
|
|
!= ICS_MAX_DEVICE_BUTTONS)
|
|
{
|
|
TiXmlElement binder( "MouseButtonBinder" );
|
|
|
|
unsigned int button = getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE);
|
|
if(button == SDL_BUTTON_LEFT)
|
|
{
|
|
binder.SetAttribute( "button", "LEFT" );
|
|
}
|
|
else if(button == SDL_BUTTON_MIDDLE)
|
|
{
|
|
binder.SetAttribute( "button", "MIDDLE" );
|
|
}
|
|
else if(button == SDL_BUTTON_RIGHT)
|
|
{
|
|
binder.SetAttribute( "button", "RIGHT" );
|
|
}
|
|
else
|
|
{
|
|
binder.SetAttribute( "button", ToString<unsigned int>(button).c_str() );
|
|
}
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
|
|
!= ICS_MAX_DEVICE_BUTTONS)
|
|
{
|
|
TiXmlElement binder( "MouseButtonBinder" );
|
|
|
|
unsigned int button = getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE);
|
|
if(button == SDL_BUTTON_LEFT)
|
|
{
|
|
binder.SetAttribute( "button", "LEFT" );
|
|
}
|
|
else if(button == SDL_BUTTON_MIDDLE)
|
|
{
|
|
binder.SetAttribute( "button", "MIDDLE" );
|
|
}
|
|
else if(button == SDL_BUTTON_RIGHT)
|
|
{
|
|
binder.SetAttribute( "button", "RIGHT" );
|
|
}
|
|
else
|
|
{
|
|
binder.SetAttribute( "button", ToString<unsigned int>(button).c_str() );
|
|
}
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
JoystickIDList::const_iterator it = mJoystickIDList.begin();
|
|
while(it != mJoystickIDList.end())
|
|
{
|
|
int deviceId = *it;
|
|
|
|
if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)
|
|
!= /*NamedAxis::*/UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "JoystickAxisBinder" );
|
|
|
|
binder.SetAttribute( "axis", ToString<int>(
|
|
getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)
|
|
!= /*NamedAxis::*/UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "JoystickAxisBinder" );
|
|
|
|
binder.SetAttribute( "axis", ToString<int>(
|
|
getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)
|
|
!= ICS_MAX_DEVICE_BUTTONS)
|
|
{
|
|
TiXmlElement binder( "JoystickButtonBinder" );
|
|
|
|
binder.SetAttribute( "button", ToString<unsigned int>(
|
|
getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)
|
|
!= ICS_MAX_DEVICE_BUTTONS)
|
|
{
|
|
TiXmlElement binder( "JoystickButtonBinder" );
|
|
|
|
binder.SetAttribute( "button", ToString<unsigned int>(
|
|
getJoystickButtonBinding(*o, *it, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE).index >= 0)
|
|
{
|
|
TiXmlElement binder( "JoystickPOVBinder" );
|
|
|
|
POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE);
|
|
|
|
binder.SetAttribute( "pov", ToString<int>(POVPair.index).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
if(POVPair.axis == ICS::InputControlSystem::EastWest)
|
|
{
|
|
binder.SetAttribute( "axis", "EastWest" );
|
|
}
|
|
else
|
|
{
|
|
binder.SetAttribute( "axis", "NorthSouth" );
|
|
}
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE).index >= 0)
|
|
{
|
|
TiXmlElement binder( "JoystickPOVBinder" );
|
|
|
|
POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE);
|
|
|
|
binder.SetAttribute( "pov", ToString<int>(POVPair.index).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
if(POVPair.axis == ICS::InputControlSystem::EastWest)
|
|
{
|
|
binder.SetAttribute( "axis", "EastWest" );
|
|
}
|
|
else
|
|
{
|
|
binder.SetAttribute( "axis", "NorthSouth" );
|
|
}
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)
|
|
!= /*NamedAxis::*/UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "JoystickSliderBinder" );
|
|
|
|
binder.SetAttribute( "slider", ToString<int>(
|
|
getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "INCREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)
|
|
!= /*NamedAxis::*/UNASSIGNED)
|
|
{
|
|
TiXmlElement binder( "JoystickSliderBinder" );
|
|
|
|
binder.SetAttribute( "slider", ToString<int>(
|
|
getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
|
|
|
|
binder.SetAttribute( "direction", "DECREASE" );
|
|
|
|
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
it++;
|
|
}
|
|
|
|
|
|
std::list<Channel*> channels = (*o)->getAttachedChannels();
|
|
for(std::list<Channel*>::iterator it = channels.begin() ;
|
|
it != channels.end() ; it++)
|
|
{
|
|
TiXmlElement binder( "Channel" );
|
|
|
|
binder.SetAttribute( "number", ToString<int>((*it)->getNumber()).c_str() );
|
|
|
|
Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction;
|
|
if(direction == Channel/*::ChannelDirection*/::DIRECT)
|
|
{
|
|
binder.SetAttribute( "direction", "DIRECT" );
|
|
}
|
|
else
|
|
{
|
|
binder.SetAttribute( "direction", "INVERSE" );
|
|
}
|
|
|
|
float percentage = (*it)->getAttachedControlBinding(*o).percentage;
|
|
binder.SetAttribute( "percentage", ToString<float>(percentage).c_str() );
|
|
|
|
control.InsertEndChild(binder);
|
|
}
|
|
|
|
Controller.InsertEndChild(control);
|
|
}
|
|
|
|
doc.InsertEndChild(Controller);
|
|
return doc.SaveFile();
|
|
}
|
|
|
|
void InputControlSystem::update(float lTimeSinceLastFrame)
|
|
{
|
|
if(mActive)
|
|
{
|
|
std::vector<Control *>::const_iterator it;
|
|
for(it=mControls.begin(); it!=mControls.end(); ++it)
|
|
{
|
|
(*it)->update(lTimeSinceLastFrame);
|
|
}
|
|
}
|
|
|
|
//! @todo Future versions should consider channel exponentials and mixtures, so
|
|
// after updating Controls, Channels should be updated according to their values
|
|
}
|
|
|
|
float InputControlSystem::getChannelValue(int i)
|
|
{
|
|
return std::max<float>(0.0,std::min<float>(1.0,mChannels[i]->getValue()));
|
|
}
|
|
|
|
float InputControlSystem::getControlValue(int i)
|
|
{
|
|
return mControls[i]->getValue();
|
|
}
|
|
|
|
void InputControlSystem::addJoystick(int deviceId)
|
|
{
|
|
ICS_LOG("Adding joystick (device id: " + ToString<int>(deviceId) + ")");
|
|
|
|
for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++)
|
|
{
|
|
if(mControlsJoystickAxisBinderMap[deviceId].find(j) == mControlsJoystickAxisBinderMap[deviceId].end())
|
|
{
|
|
ControlAxisBinderItem controlJoystickBinderItem;
|
|
controlJoystickBinderItem.direction = Control::STOP;
|
|
controlJoystickBinderItem.control = NULL;
|
|
mControlsJoystickAxisBinderMap[deviceId][j] = controlJoystickBinderItem;
|
|
}
|
|
}
|
|
|
|
mJoystickIDList.push_back(deviceId);
|
|
}
|
|
|
|
Control* InputControlSystem::findControl(std::string name)
|
|
{
|
|
if(mActive)
|
|
{
|
|
std::vector<Control *>::const_iterator it;
|
|
for(it = mControls.begin(); it != mControls.end(); ++it)
|
|
{
|
|
if( ((Control*)(*it))->getName() == name)
|
|
{
|
|
return (Control*)(*it);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void InputControlSystem::enableDetectingBindingState(Control* control
|
|
, Control::ControlChangingDirection direction)
|
|
{
|
|
mDetectingBindingControl = control;
|
|
mDetectingBindingDirection = direction;
|
|
|
|
mMouseAxisBindingInitialValues[0] = ICS_MOUSE_AXIS_BINDING_NULL_VALUE;
|
|
}
|
|
|
|
void InputControlSystem::cancelDetectingBindingState()
|
|
{
|
|
mDetectingBindingControl = NULL;
|
|
}
|
|
|
|
void InputControlSystem::fillSDLKeysMap()
|
|
{
|
|
mKeys["UNASSIGNED"]= SDLK_UNKNOWN;
|
|
mKeys["ESCAPE"]= SDLK_ESCAPE;
|
|
mKeys["1"]= SDLK_1;
|
|
mKeys["2"]= SDLK_2;
|
|
mKeys["3"]= SDLK_3;
|
|
mKeys["4"]= SDLK_4;
|
|
mKeys["5"]= SDLK_5;
|
|
mKeys["6"]= SDLK_6;
|
|
mKeys["7"]= SDLK_7;
|
|
mKeys["8"]= SDLK_8;
|
|
mKeys["9"]= SDLK_9;
|
|
mKeys["0"]= SDLK_0;
|
|
mKeys["MINUS"]= SDLK_MINUS;
|
|
mKeys["EQUALS"]= SDLK_EQUALS;
|
|
mKeys["BACK"]= SDLK_BACKSPACE;
|
|
mKeys["TAB"]= SDLK_TAB;
|
|
mKeys["Q"]= SDLK_q;
|
|
mKeys["W"]= SDLK_w;
|
|
mKeys["E"]= SDLK_e;
|
|
mKeys["R"]= SDLK_r;
|
|
mKeys["T"]= SDLK_t;
|
|
mKeys["Y"]= SDLK_y;
|
|
mKeys["U"]= SDLK_u;
|
|
mKeys["I"]= SDLK_i;
|
|
mKeys["O"]= SDLK_o;
|
|
mKeys["P"]= SDLK_p;
|
|
mKeys["LBRACKET"]= SDLK_LEFTBRACKET;
|
|
mKeys["RBRACKET"]= SDLK_RIGHTBRACKET;
|
|
mKeys["RETURN"]= SDLK_RETURN;
|
|
mKeys["LCONTROL"]= SDLK_LCTRL;
|
|
mKeys["A"]= SDLK_a;
|
|
mKeys["S"]= SDLK_s;
|
|
mKeys["D"]= SDLK_d;
|
|
mKeys["F"]= SDLK_f;
|
|
mKeys["G"]= SDLK_g;
|
|
mKeys["H"]= SDLK_h;
|
|
mKeys["J"]= SDLK_j;
|
|
mKeys["K"]= SDLK_k;
|
|
mKeys["L"]= SDLK_l;
|
|
mKeys["SEMICOLON"]= SDLK_SEMICOLON;
|
|
mKeys["APOSTROPHE"]= SDLK_QUOTE;
|
|
mKeys["GRAVE"]= SDLK_BACKQUOTE;
|
|
mKeys["LSHIFT"]= SDLK_LSHIFT;
|
|
mKeys["BACKSLASH"]= SDLK_BACKSLASH;
|
|
mKeys["Z"]= SDLK_z;
|
|
mKeys["X"]= SDLK_x;
|
|
mKeys["C"]= SDLK_c;
|
|
mKeys["V"]= SDLK_v;
|
|
mKeys["B"]= SDLK_b;
|
|
mKeys["N"]= SDLK_n;
|
|
mKeys["M"]= SDLK_m;
|
|
mKeys["COMMA"]= SDLK_COMMA;
|
|
mKeys["PERIOD"]= SDLK_PERIOD;
|
|
mKeys["SLASH"]= SDLK_SLASH;
|
|
mKeys["RSHIFT"]= SDLK_RSHIFT;
|
|
mKeys["MULTIPLY"]= SDLK_ASTERISK;
|
|
mKeys["LMENU"]= SDLK_LALT;
|
|
mKeys["SPACE"]= SDLK_SPACE;
|
|
mKeys["CAPITAL"]= SDLK_CAPSLOCK;
|
|
mKeys["F1"]= SDLK_F1;
|
|
mKeys["F2"]= SDLK_F2;
|
|
mKeys["F3"]= SDLK_F3;
|
|
mKeys["F4"]= SDLK_F4;
|
|
mKeys["F5"]= SDLK_F5;
|
|
mKeys["F6"]= SDLK_F6;
|
|
mKeys["F7"]= SDLK_F7;
|
|
mKeys["F8"]= SDLK_F8;
|
|
mKeys["F9"]= SDLK_F9;
|
|
mKeys["F10"]= SDLK_F10;
|
|
mKeys["F11"]= SDLK_F11;
|
|
mKeys["F12"]= SDLK_F12;
|
|
mKeys["NUMLOCK"]= SDLK_NUMLOCKCLEAR;
|
|
mKeys["SCROLL"]= SDLK_SCROLLLOCK;
|
|
mKeys["NUMPAD7"]= SDLK_KP_7;
|
|
mKeys["NUMPAD8"]= SDLK_KP_8;
|
|
mKeys["NUMPAD9"]= SDLK_KP_9;
|
|
mKeys["SUBTRACT"]= SDLK_KP_MINUS;
|
|
mKeys["NUMPAD4"]= SDLK_KP_4;
|
|
mKeys["NUMPAD5"]= SDLK_KP_5;
|
|
mKeys["NUMPAD6"]= SDLK_KP_6;
|
|
mKeys["ADD"]= SDLK_KP_PLUS;
|
|
mKeys["NUMPAD1"]= SDLK_KP_1;
|
|
mKeys["NUMPAD2"]= SDLK_KP_2;
|
|
mKeys["NUMPAD3"]= SDLK_KP_3;
|
|
mKeys["NUMPAD0"]= SDLK_KP_0;
|
|
mKeys["DECIMAL"]= SDLK_KP_DECIMAL;
|
|
mKeys["RCONTROL"]= SDLK_RCTRL;
|
|
mKeys["DIVIDE"]= SDLK_SLASH;
|
|
mKeys["SYSRQ"]= SDLK_SYSREQ;
|
|
mKeys["PRNTSCRN"] = SDLK_PRINTSCREEN;
|
|
mKeys["RMENU"]= SDLK_RALT;
|
|
mKeys["PAUSE"]= SDLK_PAUSE;
|
|
mKeys["HOME"]= SDLK_HOME;
|
|
mKeys["UP"]= SDLK_UP;
|
|
mKeys["PGUP"]= SDLK_PAGEUP;
|
|
mKeys["LEFT"]= SDLK_LEFT;
|
|
mKeys["RIGHT"]= SDLK_RIGHT;
|
|
mKeys["END"]= SDLK_END;
|
|
mKeys["DOWN"]= SDLK_DOWN;
|
|
mKeys["PGDOWN"]= SDLK_PAGEDOWN;
|
|
mKeys["INSERT"]= SDLK_INSERT;
|
|
mKeys["DELETE"]= SDLK_DELETE;
|
|
|
|
mKeys["NUMPADENTER"]= SDLK_KP_ENTER;
|
|
|
|
for(std::map<std::string, SDL_Keycode>::iterator it = mKeys.begin()
|
|
; it != mKeys.end() ; it++)
|
|
{
|
|
mKeyCodes[ it->second ] = it->first;
|
|
}
|
|
}
|
|
|
|
std::string InputControlSystem::keyCodeToString(SDL_Keycode key)
|
|
{
|
|
return mKeyCodes[key];
|
|
}
|
|
|
|
SDL_Keycode InputControlSystem::stringToKeyCode(std::string key)
|
|
{
|
|
return mKeys[key];
|
|
}
|
|
|
|
void InputControlSystem::adjustMouseRegion(Uint16 width, Uint16 height)
|
|
{
|
|
mClientWidth = width;
|
|
mClientHeight = height;
|
|
}
|
|
}
|