Input system rewrite
parent
39f87bee0e
commit
86d6f190bf
@ -1,28 +0,0 @@
|
||||
#include "mouselookevent.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include <OIS/OIS.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
using namespace OIS;
|
||||
using namespace MWInput;
|
||||
|
||||
void MouseLookEvent::event(Type type, int index, const void *p)
|
||||
{
|
||||
if (type != EV_MouseMove || mDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
MouseEvent *arg = (MouseEvent*)(p);
|
||||
|
||||
float x = arg->state.X.rel * sensX;
|
||||
float y = arg->state.Y.rel * sensY;
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#ifndef _MWINPUT_MOUSELOOKEVENT_H
|
||||
#define _MWINPUT_MOUSELOOKEVENT_H
|
||||
|
||||
/*
|
||||
A mouse-look class for Ogre. Accepts input events from Mangle::Input
|
||||
and translates them.
|
||||
|
||||
You can adjust the mouse sensibility and switch to a different
|
||||
camera. The mouselook class also has an optional wrap protection
|
||||
that keeps the camera from flipping upside down.
|
||||
|
||||
You can disable the mouse looker at any time by calling
|
||||
setCamera(NULL), and reenable it by setting the camera back.
|
||||
|
||||
NOTE: The current implementation will ONLY work for native OIS
|
||||
events.
|
||||
*/
|
||||
|
||||
#include <mangle/input/event.hpp>
|
||||
|
||||
namespace MWInput
|
||||
{
|
||||
class MouseLookEvent : public Mangle::Input::Event
|
||||
{
|
||||
float sensX, sensY; // Mouse sensibility
|
||||
bool flipProt; // Flip protection
|
||||
bool mDisabled;
|
||||
|
||||
public:
|
||||
MouseLookEvent(float sX = 0.2, float sY = 0.2, bool prot=true)
|
||||
: sensX(sX), sensY(sY), flipProt(prot)
|
||||
{}
|
||||
|
||||
void setSens(float sX, float sY) {
|
||||
sensX = sX;
|
||||
sensY = sY;
|
||||
}
|
||||
|
||||
void setProt(bool p) {
|
||||
flipProt = p;
|
||||
}
|
||||
|
||||
void disable() {
|
||||
mDisabled = true;
|
||||
}
|
||||
|
||||
void enable() {
|
||||
mDisabled = false;
|
||||
}
|
||||
|
||||
void event(Type type, int index, const void *p);
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<MouseLookEvent> MouseLookEventPtr;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,20 @@
|
||||
set(OICS_LIBRARY "oics")
|
||||
|
||||
# Sources
|
||||
|
||||
set(OICS_SOURCE_FILES
|
||||
ICSChannel.cpp
|
||||
ICSControl.cpp
|
||||
ICSInputControlSystem.cpp
|
||||
ICSInputControlSystem_keyboard.cpp
|
||||
ICSInputControlSystem_mouse.cpp
|
||||
ICSInputControlSystem_joystick.cpp
|
||||
tinyxml.cpp
|
||||
tinyxmlparser.cpp
|
||||
tinyxmlerror.cpp
|
||||
tinystr.cpp
|
||||
)
|
||||
|
||||
add_library(${OICS_LIBRARY} STATIC ${OICS_SOURCE_FILES})
|
||||
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
@ -0,0 +1,258 @@
|
||||
/* -------------------------------------------------------
|
||||
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"
|
||||
|
||||
#define B1(t) (t*t)
|
||||
#define B2(t) (2*t*(1-t))
|
||||
#define B3(t) ((1-t)*(1-t))
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
Channel::Channel(int number, float initialValue
|
||||
, float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
|
||||
: mNumber(number)
|
||||
, mValue(initialValue)
|
||||
, mSymmetricAt(symmetricAt)
|
||||
, mBezierStep(bezierStep)
|
||||
{
|
||||
mBezierMidPoint.x = bezierMidPointX;
|
||||
mBezierMidPoint.y = bezierMidPointY;
|
||||
|
||||
setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep);
|
||||
}
|
||||
|
||||
float Channel::getValue()
|
||||
{
|
||||
if(mValue == 0 || mValue == 1)
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
BezierFunction::iterator it = mBezierFunction.begin();
|
||||
//size_t size_minus_1 = mBezierFunction.size() - 1;
|
||||
BezierFunction::iterator last = mBezierFunction.end();
|
||||
last--;
|
||||
for ( ; it != last ; )
|
||||
{
|
||||
BezierPoint left = (*it);
|
||||
BezierPoint right = (*(++it));
|
||||
|
||||
if( (left.x <= mValue) && (right.x > mValue) )
|
||||
{
|
||||
float val = left.y - (left.x - mValue) * (left.y - right.y) / (left.x - right.x);
|
||||
|
||||
return std::max<float>(0.0,std::min<float>(1.0, val));
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Channel::setValue(float value)
|
||||
{
|
||||
float previousValue = this->getValue();
|
||||
|
||||
mValue = value;
|
||||
|
||||
if(previousValue != value)
|
||||
{
|
||||
notifyListeners(previousValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::notifyListeners(float previousValue)
|
||||
{
|
||||
std::list<ChannelListener*>::iterator pos = mListeners.begin();
|
||||
while (pos != mListeners.end())
|
||||
{
|
||||
((ChannelListener* )(*pos))->channelChanged((Channel*)this, this->getValue(), previousValue);
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::addControl(Control* control, Channel::ChannelDirection dir, float percentage)
|
||||
{
|
||||
ControlChannelBinderItem ccBinderItem;
|
||||
ccBinderItem.control = control;
|
||||
ccBinderItem.direction = dir;
|
||||
ccBinderItem.percentage = percentage;
|
||||
|
||||
mAttachedControls.push_back(ccBinderItem);
|
||||
}
|
||||
|
||||
Channel::ControlChannelBinderItem Channel::getAttachedControlBinding(Control* control)
|
||||
{
|
||||
for(std::vector<ControlChannelBinderItem>::iterator it = mAttachedControls.begin() ;
|
||||
it != mAttachedControls.end() ; it++)
|
||||
{
|
||||
if((*it).control == control)
|
||||
{
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
ControlChannelBinderItem nullBinderItem;
|
||||
nullBinderItem.control = NULL;
|
||||
nullBinderItem.direction = Channel/*::ChannelDirection*/::DIRECT;
|
||||
nullBinderItem.percentage = 0;
|
||||
return nullBinderItem;
|
||||
}
|
||||
|
||||
void Channel::update()
|
||||
{
|
||||
if(this->getControlsCount() == 1)
|
||||
{
|
||||
ControlChannelBinderItem ccBinderItem = mAttachedControls.back();
|
||||
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
|
||||
|
||||
if(ccBinderItem.direction == ICS::Channel::DIRECT)
|
||||
{
|
||||
this->setValue(ccBinderItem.control->getInitialValue() + (ccBinderItem.percentage * diff));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setValue(ccBinderItem.control->getInitialValue() - (ccBinderItem.percentage * diff));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float val = 0;
|
||||
std::vector<ControlChannelBinderItem>::const_iterator it;
|
||||
for(it=mAttachedControls.begin(); it!=mAttachedControls.end(); ++it)
|
||||
{
|
||||
ControlChannelBinderItem ccBinderItem = (*it);
|
||||
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();
|
||||
|
||||
if(ccBinderItem.direction == ICS::Channel::DIRECT)
|
||||
{
|
||||
val += (ccBinderItem.percentage * diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
val -= (ccBinderItem.percentage * diff);
|
||||
}
|
||||
}
|
||||
|
||||
if(mAttachedControls.size() > 0)
|
||||
{
|
||||
this->setValue(mAttachedControls.begin()->control->getInitialValue() + val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::setBezierFunction(float bezierMidPointY, float bezierMidPointX, float symmetricAt, float bezierStep)
|
||||
{
|
||||
mBezierMidPoint.x = bezierMidPointX;
|
||||
mBezierMidPoint.y = bezierMidPointY;
|
||||
mBezierStep = bezierStep;
|
||||
mSymmetricAt = symmetricAt;
|
||||
|
||||
mBezierFunction.clear();
|
||||
|
||||
BezierPoint start;
|
||||
start.x = 0;
|
||||
start.y = 0;
|
||||
|
||||
BezierPoint end;
|
||||
end.x = 1;
|
||||
end.y = 1;
|
||||
mBezierFunction.push_front(end);
|
||||
|
||||
FilterInterval interval;
|
||||
interval.startX = start.x;
|
||||
interval.startY = start.y;
|
||||
interval.midX = mBezierMidPoint.x;
|
||||
interval.midY = mBezierMidPoint.y;
|
||||
interval.endX = end.x;
|
||||
interval.endY = end.y;
|
||||
interval.step = bezierStep;
|
||||
mIntervals.push_back(interval);
|
||||
|
||||
if(!(mBezierMidPoint.x == 0.5 && mBezierMidPoint.y == 0.5))
|
||||
{
|
||||
float t = mBezierStep;
|
||||
while(t < 1)
|
||||
{
|
||||
BezierPoint p;
|
||||
p.x = start.x * B1(t) + mBezierMidPoint.x * B2(t) + end.x * B3(t);
|
||||
p.y = start.y * B1(t) + mBezierMidPoint.y * B2(t) + end.y * B3(t);
|
||||
mBezierFunction.push_front(p);
|
||||
|
||||
t += mBezierStep;
|
||||
}
|
||||
}
|
||||
|
||||
mBezierFunction.push_front(start);
|
||||
}
|
||||
|
||||
void Channel::addBezierInterval(float startX, float startY, float midX, float midY
|
||||
, float endX, float endY, float step)
|
||||
{
|
||||
FilterInterval interval;
|
||||
interval.startX = startX;
|
||||
interval.startY = startY;
|
||||
interval.midX = midX;
|
||||
interval.midY = midY;
|
||||
interval.endX = endX;
|
||||
interval.endY = endY;
|
||||
interval.step = step;
|
||||
mIntervals.push_back(interval);
|
||||
|
||||
float t = 0;
|
||||
while(t <= 1)
|
||||
{
|
||||
BezierPoint p;
|
||||
p.x = startX * B1(t) + midX * B2(t) + endX * B3(t);
|
||||
p.y = startY * B1(t) + midY * B2(t) + endY * B3(t);
|
||||
|
||||
BezierFunction::iterator it = mBezierFunction.begin();
|
||||
while( it != mBezierFunction.end() )
|
||||
{
|
||||
BezierPoint left = (*it);
|
||||
BezierPoint right;
|
||||
++it;
|
||||
if( it != mBezierFunction.end() )
|
||||
{
|
||||
right = (*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
right.x = endX;
|
||||
right.y = endY;
|
||||
}
|
||||
|
||||
if(p.x > left.x && p.x < right.x)
|
||||
{
|
||||
mBezierFunction.insert(it, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
t += 1.0f / ((endX-startX)/step);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
#ifndef _Channel_H_
|
||||
#define _Channel_H_
|
||||
|
||||
#include "ICSPrerequisites.h"
|
||||
|
||||
#include "ICSChannelListener.h"
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
struct FilterInterval{
|
||||
//std::string type; //! @todo uncomment when more types implemented
|
||||
float startX;
|
||||
float startY;
|
||||
float midX;
|
||||
float midY;
|
||||
float endX;
|
||||
float endY;
|
||||
float step;
|
||||
};
|
||||
|
||||
typedef std::list<FilterInterval> IntervalList;
|
||||
|
||||
class DllExport Channel
|
||||
{
|
||||
public:
|
||||
enum ChannelDirection
|
||||
{
|
||||
INVERSE = -1, DIRECT = 1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ChannelDirection direction;
|
||||
float percentage;
|
||||
Control* control;
|
||||
} ControlChannelBinderItem;
|
||||
|
||||
|
||||
Channel(int number, float initialValue = 0.5
|
||||
, float bezierMidPointY = 0.5, float bezierMidPointX = 0.5
|
||||
, float symmetricAt = 0, float bezierStep = 0.2); //! @todo implement symetry
|
||||
~Channel(){};
|
||||
|
||||
void setValue(float value);
|
||||
float getValue();
|
||||
|
||||
inline int getNumber(){ return mNumber; };
|
||||
|
||||
void addControl(Control* control, Channel::ChannelDirection dir, float percentage);
|
||||
inline size_t getControlsCount(){ return mAttachedControls.size(); };
|
||||
std::vector<ControlChannelBinderItem> getAttachedControls(){ return mAttachedControls; };
|
||||
ControlChannelBinderItem getAttachedControlBinding(Control* control);
|
||||
|
||||
void addListener(ChannelListener* ob){ mListeners.push_back(ob); };
|
||||
void removeListener(ChannelListener* ob){ mListeners.remove(ob); };
|
||||
|
||||
void update();
|
||||
|
||||
void setBezierFunction(float bezierMidPointY, float bezierMidPointX = 0.5
|
||||
, float symmetricAt = 0, float bezierStep = 0.2);
|
||||
|
||||
void addBezierInterval(float startX, float startY, float midX, float midY
|
||||
, float endX, float endY, float step = 0.1);
|
||||
|
||||
IntervalList& getIntervals(){ return mIntervals; };
|
||||
|
||||
protected:
|
||||
|
||||
int mNumber;
|
||||
float mValue;
|
||||
|
||||
struct BezierPoint{
|
||||
float x;
|
||||
float y;
|
||||
bool operator < (const BezierPoint& other){ return x < other.x; }
|
||||
};
|
||||
|
||||
typedef std::list<BezierPoint> BezierFunction;
|
||||
|
||||
BezierPoint mBezierMidPoint;
|
||||
BezierFunction mBezierFunction;
|
||||
float mSymmetricAt;
|
||||
float mBezierStep;
|
||||
|
||||
IntervalList mIntervals;
|
||||
|
||||
std::vector<ControlChannelBinderItem> mAttachedControls;
|
||||
|
||||
std::list<ChannelListener* > mListeners;
|
||||
void notifyListeners(float previousValue);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,46 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
#ifndef _ChannelListener_H_
|
||||
#define _ChannelListener_H_
|
||||
|
||||
#include "ICSPrerequisites.h"
|
||||
|
||||
#include "ICSChannel.h"
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
|
||||
class DllExport ChannelListener
|
||||
{
|
||||
public:
|
||||
virtual void channelChanged(Channel* channel, float currentValue, float previousValue) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,161 @@
|
||||
/* -------------------------------------------------------
|
||||
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"
|
||||
|
||||
#include "ICSControl.h"
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
Control::Control(const std::string name, bool autoChangeDirectionOnLimitsAfterStop, bool autoReverseToInitialValue
|
||||
, float initialValue, float stepSize, float stepsPerSeconds, bool axisBindable)
|
||||
: mName(name)
|
||||
, mValue(initialValue)
|
||||
, mInitialValue(initialValue)
|
||||
, mStepSize(stepSize)
|
||||
, mStepsPerSeconds(stepsPerSeconds)
|
||||
, mAutoReverseToInitialValue(autoReverseToInitialValue)
|
||||
, mIgnoreAutoReverse(false)
|
||||
, mAutoChangeDirectionOnLimitsAfterStop(autoChangeDirectionOnLimitsAfterStop)
|
||||
, mAxisBindable(axisBindable)
|
||||
, currentChangingDirection(STOP)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Control::~Control()
|
||||
{
|
||||
mAttachedChannels.clear();
|
||||
}
|
||||
|
||||
void Control::setValue(float value)
|
||||
{
|
||||
float previousValue = mValue;
|
||||
|
||||
mValue = std::max<float>(0.0,std::min<float>(1.0,value));
|
||||
|
||||
if(mValue != previousValue)
|
||||
{
|
||||
updateChannels();
|
||||
|
||||
notifyListeners(previousValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage)
|
||||
{
|
||||
mAttachedChannels.push_back(channel);
|
||||
channel->addControl(this, direction, percentage);
|
||||
}
|
||||
|
||||
void Control::updateChannels()
|
||||
{
|
||||
std::list<Channel*>::iterator pos = mAttachedChannels.begin();
|
||||
while (pos != mAttachedChannels.end())
|
||||
{
|
||||
((Channel* )(*pos))->update();
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
void Control::notifyListeners(float previousValue)
|
||||
{
|
||||
std::list<ControlListener*>::iterator pos = mListeners.begin();
|
||||
while (pos != mListeners.end())
|
||||
{
|
||||
((ControlListener* )(*pos))->controlChanged((Control*)this, this->getValue(), previousValue);
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
void Control::setChangingDirection(ControlChangingDirection direction)
|
||||
{
|
||||
currentChangingDirection = direction;
|
||||
mPendingActions.push_back(direction);
|
||||
}
|
||||
|
||||
void Control::update(float timeSinceLastFrame)
|
||||
{
|
||||
if(mPendingActions.size() > 0)
|
||||
{
|
||||
size_t timedActionsCount = 0;
|
||||
|
||||
std::list<Control::ControlChangingDirection>::iterator cached_end = mPendingActions.end();
|
||||
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
|
||||
it != cached_end ; it++)
|
||||
{
|
||||
if( (*it) != Control::STOP )
|
||||
{
|
||||
timedActionsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
float timeSinceLastFramePart = timeSinceLastFrame / std::max<size_t>(1, timedActionsCount);
|
||||
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
|
||||
it != cached_end ; it++)
|
||||
{
|
||||
if( (*it) != Control::STOP )
|
||||
{
|
||||
this->setValue(mValue +
|
||||
(((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)));
|
||||
}
|
||||
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
|
||||
{
|
||||
|
||||
if(mValue > mInitialValue)
|
||||
{
|
||||
this->setValue( std::max<float>( mInitialValue,
|
||||
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
|
||||
}
|
||||
else if(mValue < mInitialValue)
|
||||
{
|
||||
this->setValue( std::min<float>( mInitialValue,
|
||||
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))));
|
||||
}
|
||||
}
|
||||
}
|
||||
mPendingActions.clear();
|
||||
}
|
||||
else if( currentChangingDirection != Control::STOP )
|
||||
{
|
||||
this->setValue(mValue +
|
||||
(((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame)));
|
||||
}
|
||||
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
|
||||
{
|
||||
if(mValue > mInitialValue)
|
||||
{
|
||||
this->setValue( std::max<float>( mInitialValue,
|
||||
mValue - (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
|
||||
}
|
||||
else if(mValue < mInitialValue)
|
||||
{
|
||||
this->setValue( std::min<float>( mInitialValue,
|
||||
mValue + (mStepSize * mStepsPerSeconds * (timeSinceLastFrame))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
#ifndef _Control_H_
|
||||
#define _Control_H_
|
||||
|
||||
#include "ICSPrerequisites.h"
|
||||
|
||||
#include "ICSChannel.h"
|
||||
#include "ICSControlListener.h"
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
|
||||
class DllExport Control
|
||||
{
|
||||
public:
|
||||
|
||||
enum ControlChangingDirection
|
||||
{
|
||||
DECREASE = -1, STOP = 0, INCREASE = 1
|
||||
};
|
||||
|
||||
Control(const std::string name, bool autoChangeDirectionOnLimitsAfterStop = false, bool autoReverseToInitialValue = false, float initialValue = 0.5, float stepSize = 0.1, float stepsPerSeconds = 2.0, bool axisBindable = true);
|
||||
~Control();
|
||||
|
||||
void setChangingDirection(ControlChangingDirection direction);
|
||||
inline ControlChangingDirection getChangingDirection(){ return currentChangingDirection; };
|
||||
|
||||
void setValue(float value);
|
||||
inline float getValue(){ return mValue; };
|
||||
inline float getInitialValue(){ return mInitialValue; };
|
||||
|
||||
void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0);
|
||||
std::list<Channel*> getAttachedChannels(){ return mAttachedChannels; };
|
||||
|
||||
inline float getStepSize(){ return mStepSize; };
|
||||
inline float getStepsPerSeconds(){ return mStepsPerSeconds; };
|
||||
|
||||
inline void setIgnoreAutoReverse(bool value){ mIgnoreAutoReverse = value; }; // mouse disable autoreverse
|
||||
inline bool isAutoReverseIgnored(){ return mIgnoreAutoReverse; };
|
||||
inline bool getAutoReverse(){ return mAutoReverseToInitialValue; };
|
||||
|
||||
inline bool getAutoChangeDirectionOnLimitsAfterStop(){ return mAutoChangeDirectionOnLimitsAfterStop; };
|
||||
|
||||
inline std::string getName(){ return mName; };
|
||||
|
||||
inline bool isAxisBindable(){ return mAxisBindable; };
|
||||
inline void setAxisBindable(bool value){ mAxisBindable = value; };
|
||||
|
||||
inline void addListener(ControlListener* ob){ mListeners.push_back(ob); };
|
||||
inline void removeListener(ControlListener* ob){ mListeners.remove(ob); };
|
||||
|
||||
void update(float timeSinceLastFrame);
|
||||
|
||||
protected:
|
||||
float mValue;
|
||||
float mInitialValue;
|
||||
std::string mName;
|
||||
float mStepSize;
|
||||
float mStepsPerSeconds;
|
||||
bool mAutoReverseToInitialValue;
|
||||
bool mIgnoreAutoReverse;
|
||||
bool mAutoChangeDirectionOnLimitsAfterStop;
|
||||
bool mAxisBindable;
|
||||
|
||||
Control::ControlChangingDirection currentChangingDirection;
|
||||
std::list<Channel*> mAttachedChannels;
|
||||
|
||||
std::list<ControlListener*> mListeners;
|
||||
|
||||
std::list<Control::ControlChangingDirection> mPendingActions;
|
||||
|
||||
protected:
|
||||
|
||||
void updateChannels();
|
||||
void notifyListeners(float previousValue);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,46 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
#ifndef _ControlListener_H_
|
||||
#define _ControlListener_H_
|
||||
|
||||
#include "ICSPrerequisites.h"
|
||||
|
||||
#include "ICSControl.h"
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
|
||||
class DllExport ControlListener
|
||||
{
|
||||
public:
|
||||
virtual void controlChanged(Control* control, float currentValue, float previousValue) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,929 @@
|
||||
/* -------------------------------------------------------
|
||||
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->fillOISKeysMap();
|
||||
|
||||
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) != OIS::KC_UNASSIGNED)
|
||||
{
|
||||
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) != OIS::KC_UNASSIGNED)
|
||||
{
|
||||
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 == OIS::/*MouseButtonID::*/MB_Left)
|
||||
{
|
||||
binder.SetAttribute( "button", "LEFT" );
|
||||
}
|
||||
else if(button == OIS::/*MouseButtonID::*/MB_Middle)
|
||||
{
|
||||
binder.SetAttribute( "button", "MIDDLE" );
|
||||
}
|
||||
else if(button == OIS::/*MouseButtonID::*/MB_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 == OIS::/*MouseButtonID::*/MB_Left)
|
||||
{
|
||||
binder.SetAttribute( "button", "LEFT" );
|
||||
}
|
||||
else if(button == OIS::/*MouseButtonID::*/MB_Middle)
|
||||
{
|
||||
binder.SetAttribute( "button", "MIDDLE" );
|
||||
}
|
||||
else if(button == OIS::/*MouseButtonID::*/MB_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::fillOISKeysMap()
|
||||
{
|
||||
mKeys["UNASSIGNED"]= OIS::KC_UNASSIGNED;
|
||||
mKeys["ESCAPE"]= OIS::KC_ESCAPE;
|
||||
mKeys["1"]= OIS::KC_1;
|
||||
mKeys["2"]= OIS::KC_2;
|
||||
mKeys["3"]= OIS::KC_3;
|
||||
mKeys["4"]= OIS::KC_4;
|
||||
mKeys["5"]= OIS::KC_5;
|
||||
mKeys["6"]= OIS::KC_6;
|
||||
mKeys["7"]= OIS::KC_7;
|
||||
mKeys["8"]= OIS::KC_8;
|
||||
mKeys["9"]= OIS::KC_9;
|
||||
mKeys["0"]= OIS::KC_0;
|
||||
mKeys["MINUS"]= OIS::KC_MINUS;
|
||||
mKeys["EQUALS"]= OIS::KC_EQUALS;
|
||||
mKeys["BACK"]= OIS::KC_BACK;
|
||||
mKeys["TAB"]= OIS::KC_TAB;
|
||||
mKeys["Q"]= OIS::KC_Q;
|
||||
mKeys["W"]= OIS::KC_W;
|
||||
mKeys["E"]= OIS::KC_E;
|
||||
mKeys["R"]= OIS::KC_R;
|
||||
mKeys["T"]= OIS::KC_T;
|
||||
mKeys["Y"]= OIS::KC_Y;
|
||||
mKeys["U"]= OIS::KC_U;
|
||||
mKeys["I"]= OIS::KC_I;
|
||||
mKeys["O"]= OIS::KC_O;
|
||||
mKeys["P"]= OIS::KC_P;
|
||||
mKeys["LBRACKET"]= OIS::KC_LBRACKET;
|
||||
mKeys["RBRACKET"]= OIS::KC_RBRACKET;
|
||||
mKeys["RETURN"]= OIS::KC_RETURN;
|
||||
mKeys["LCONTROL"]= OIS::KC_LCONTROL;
|
||||
mKeys["A"]= OIS::KC_A;
|
||||
mKeys["S"]= OIS::KC_S;
|
||||
mKeys["D"]= OIS::KC_D;
|
||||
mKeys["F"]= OIS::KC_F;
|
||||
mKeys["G"]= OIS::KC_G;
|
||||
mKeys["H"]= OIS::KC_H;
|
||||
mKeys["J"]= OIS::KC_J;
|
||||
mKeys["K"]= OIS::KC_K;
|
||||
mKeys["L"]= OIS::KC_L;
|
||||
mKeys["SEMICOLON"]= OIS::KC_SEMICOLON;
|
||||
mKeys["APOSTROPHE"]= OIS::KC_APOSTROPHE;
|
||||
mKeys["GRAVE"]= OIS::KC_GRAVE;
|
||||
mKeys["LSHIFT"]= OIS::KC_LSHIFT;
|
||||
mKeys["BACKSLASH"]= OIS::KC_BACKSLASH;
|
||||
mKeys["Z"]= OIS::KC_Z;
|
||||
mKeys["X"]= OIS::KC_X;
|
||||
mKeys["C"]= OIS::KC_C;
|
||||
mKeys["V"]= OIS::KC_V;
|
||||
mKeys["B"]= OIS::KC_B;
|
||||
mKeys["N"]= OIS::KC_N;
|
||||
mKeys["M"]= OIS::KC_M;
|
||||
mKeys["COMMA"]= OIS::KC_COMMA;
|
||||
mKeys["PERIOD"]= OIS::KC_PERIOD;
|
||||
mKeys["SLASH"]= OIS::KC_SLASH;
|
||||
mKeys["RSHIFT"]= OIS::KC_RSHIFT;
|
||||
mKeys["MULTIPLY"]= OIS::KC_MULTIPLY;
|
||||
mKeys["LMENU"]= OIS::KC_LMENU;
|
||||
mKeys["SPACE"]= OIS::KC_SPACE;
|
||||
mKeys["CAPITAL"]= OIS::KC_CAPITAL;
|
||||
mKeys["F1"]= OIS::KC_F1;
|
||||
mKeys["F2"]= OIS::KC_F2;
|
||||
mKeys["F3"]= OIS::KC_F3;
|
||||
mKeys["F4"]= OIS::KC_F4;
|
||||
mKeys["F5"]= OIS::KC_F5;
|
||||
mKeys["F6"]= OIS::KC_F6;
|
||||
mKeys["F7"]= OIS::KC_F7;
|
||||
mKeys["F8"]= OIS::KC_F8;
|
||||
mKeys["F9"]= OIS::KC_F9;
|
||||
mKeys["F10"]= OIS::KC_F10;
|
||||
mKeys["F11"]= OIS::KC_F11;
|
||||
mKeys["F12"]= OIS::KC_F12;
|
||||
mKeys["NUMLOCK"]= OIS::KC_NUMLOCK;
|
||||
mKeys["SCROLL"]= OIS::KC_SCROLL;
|
||||
mKeys["NUMPAD7"]= OIS::KC_NUMPAD7;
|
||||
mKeys["NUMPAD8"]= OIS::KC_NUMPAD8;
|
||||
mKeys["NUMPAD9"]= OIS::KC_NUMPAD9;
|
||||
mKeys["SUBTRACT"]= OIS::KC_SUBTRACT;
|
||||
mKeys["NUMPAD4"]= OIS::KC_NUMPAD4;
|
||||
mKeys["NUMPAD5"]= OIS::KC_NUMPAD5;
|
||||
mKeys["NUMPAD6"]= OIS::KC_NUMPAD6;
|
||||
mKeys["ADD"]= OIS::KC_ADD;
|
||||
mKeys["NUMPAD1"]= OIS::KC_NUMPAD1;
|
||||
mKeys["NUMPAD2"]= OIS::KC_NUMPAD2;
|
||||
mKeys["NUMPAD3"]= OIS::KC_NUMPAD3;
|
||||
mKeys["NUMPAD0"]= OIS::KC_NUMPAD0;
|
||||
mKeys["DECIMAL"]= OIS::KC_DECIMAL;
|
||||
mKeys["RCONTROL"]= OIS::KC_RCONTROL;
|
||||
mKeys["DIVIDE"]= OIS::KC_DIVIDE;
|
||||
mKeys["SYSRQ"]= OIS::KC_SYSRQ;
|
||||
mKeys["RMENU"]= OIS::KC_RMENU;
|
||||
mKeys["PAUSE"]= OIS::KC_PAUSE;
|
||||
mKeys["HOME"]= OIS::KC_HOME;
|
||||
mKeys["UP"]= OIS::KC_UP;
|
||||
mKeys["PGUP"]= OIS::KC_PGUP;
|
||||
mKeys["LEFT"]= OIS::KC_LEFT;
|
||||
mKeys["RIGHT"]= OIS::KC_RIGHT;
|
||||
mKeys["END"]= OIS::KC_END;
|
||||
mKeys["DOWN"]= OIS::KC_DOWN;
|
||||
mKeys["PGDOWN"]= OIS::KC_PGDOWN;
|
||||
mKeys["INSERT"]= OIS::KC_INSERT;
|
||||
mKeys["DELETE"]= OIS::KC_DELETE;
|
||||
mKeys["LWIN"]= OIS::KC_LWIN;
|
||||
mKeys["RWIN"]= OIS::KC_RWIN;
|
||||
mKeys["APPS"]= OIS::KC_APPS;
|
||||
|
||||
mKeys["NUMPADENTER"]= OIS::KC_NUMPADENTER;
|
||||
|
||||
for(std::map<std::string, OIS::KeyCode>::iterator it = mKeys.begin()
|
||||
; it != mKeys.end() ; it++)
|
||||
{
|
||||
mKeyCodes[ it->second ] = it->first;
|
||||
}
|
||||
}
|
||||
|
||||
std::string InputControlSystem::keyCodeToString(OIS::KeyCode key)
|
||||
{
|
||||
return mKeyCodes[key];
|
||||
}
|
||||
|
||||
OIS::KeyCode InputControlSystem::stringToKeyCode(std::string key)
|
||||
{
|
||||
return mKeys[key];
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
#ifndef _InputControlSystem_H_
|
||||
#define _InputControlSystem_H_
|
||||
|
||||
#include "ICSPrerequisites.h"
|
||||
|
||||
#include "ICSControl.h"
|
||||
#include "ICSChannel.h"
|
||||
|
||||
#define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() );
|
||||
#define ICS_MAX_JOYSTICK_AXIS 16
|
||||
#define ICS_MOUSE_BINDING_MARGIN 30
|
||||
#define ICS_JOYSTICK_AXIS_BINDING_MARGIN 10000
|
||||
#define ICS_JOYSTICK_SLIDER_BINDING_MARGIN 10000
|
||||
#define ICS_MOUSE_AXIS_BINDING_NULL_VALUE std::numeric_limits<int>::max()
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
class DllExport InputControlSystemLog
|
||||
{
|
||||
public:
|
||||
virtual void logMessage(const char* text) = 0;
|
||||
};
|
||||
|
||||
class DllExport InputControlSystem :
|
||||
public OIS::MouseListener,
|
||||
public OIS::KeyListener,
|
||||
public OIS::JoyStickListener
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum NamedAxis { X = -1, Y = -2, Z = -3, UNASSIGNED = -4 };
|
||||
enum POVAxis { NorthSouth = 0, EastWest = 1 };
|
||||
|
||||
typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions
|
||||
|
||||
typedef std::list<int> JoystickIDList;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int index;
|
||||
POVAxis axis;
|
||||
} POVBindingPair;
|
||||
|
||||
InputControlSystem(std::string file = "", bool active = true
|
||||
, DetectingBindingListener* detectingBindingListener = NULL
|
||||
, InputControlSystemLog* log = NULL, size_t channelCount = 16);
|
||||
~InputControlSystem();
|
||||
|
||||
std::string getFileName(){ return mFileName; };
|
||||
std::string getBaseFileName();
|
||||
|
||||
void setDetectingBindingListener(DetectingBindingListener* detectingBindingListener){ mDetectingBindingListener = detectingBindingListener; };
|
||||
DetectingBindingListener* getDetectingBindingListener(){ return mDetectingBindingListener; };
|
||||
|
||||
// in seconds
|
||||
void update(float timeSinceLastFrame);
|
||||
|
||||
inline Channel* getChannel(int i){ return mChannels[i]; };
|
||||
float getChannelValue(int i);
|
||||
inline int getChannelCount(){ return (int)mChannels.size(); };
|
||||
|
||||
inline Control* getControl(int i){ return mControls[i]; };
|
||||
float getControlValue(int i);
|
||||
inline int getControlCount(){ return (int)mControls.size(); };
|
||||
inline void addControl(Control* control){ mControls.push_back(control); };
|
||||
|
||||
Control* findControl(std::string name);
|
||||
|
||||
inline void activate(){ this->mActive = true; };
|
||||
inline void deactivate(){ this->mActive = false; };
|
||||
|
||||
void addJoystick(int deviceId);
|
||||
JoystickIDList& getJoystickIdList(){ return mJoystickIDList; };
|
||||
|
||||
// MouseListener
|
||||
bool mouseMoved(const OIS::MouseEvent &evt);
|
||||
bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID);
|
||||
bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID);
|
||||
|
||||
// KeyListener
|
||||
bool keyPressed(const OIS::KeyEvent &evt);
|
||||
bool keyReleased(const OIS::KeyEvent &evt);
|
||||
|
||||
// JoyStickListener
|
||||
bool buttonPressed(const OIS::JoyStickEvent &evt, int button);
|
||||
bool buttonReleased(const OIS::JoyStickEvent &evt, int button);
|
||||
bool axisMoved(const OIS::JoyStickEvent &evt, int axis);
|
||||
bool povMoved(const OIS::JoyStickEvent &evt, int index);
|
||||
bool sliderMoved(const OIS::JoyStickEvent &evt, int index);
|
||||
|
||||
void addKeyBinding(Control* control, OIS::KeyCode key, Control::ControlChangingDirection direction);
|
||||
void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction);
|
||||
void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
|
||||
void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction);
|
||||
void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction);
|
||||
void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction);
|
||||
void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction);
|
||||
void removeKeyBinding(OIS::KeyCode key);
|
||||
void removeMouseAxisBinding(NamedAxis axis);
|
||||
void removeMouseButtonBinding(unsigned int button);
|
||||
void removeJoystickAxisBinding(int deviceId, int axis);
|
||||
void removeJoystickButtonBinding(int deviceId, unsigned int button);
|
||||
void removeJoystickPOVBinding(int deviceId, int index, POVAxis axis);
|
||||
void removeJoystickSliderBinding(int deviceId, int index);
|
||||
|
||||
OIS::KeyCode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction);
|
||||
NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction);
|
||||
unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction);
|
||||
int getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
|
||||
unsigned int getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
|
||||
POVBindingPair getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
|
||||
int getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
|
||||
|
||||
std::string keyCodeToString(OIS::KeyCode key);
|
||||
OIS::KeyCode stringToKeyCode(std::string key);
|
||||
|
||||
void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction);
|
||||
void cancelDetectingBindingState();
|
||||
|
||||
bool save(std::string fileName = "");
|
||||
|
||||
protected:
|
||||
|
||||
void loadKeyBinders(TiXmlElement* xmlControlNode);
|
||||
void loadMouseAxisBinders(TiXmlElement* xmlControlNode);
|
||||
void loadMouseButtonBinders(TiXmlElement* xmlControlNode);
|
||||
void loadJoystickAxisBinders(TiXmlElement* xmlControlNode);
|
||||
void loadJoystickButtonBinders(TiXmlElement* xmlControlNode);
|
||||
void loadJoystickPOVBinders(TiXmlElement* xmlControlNode);
|
||||
void loadJoystickSliderBinders(TiXmlElement* xmlControlNode);
|
||||
|
||||
void addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction);
|
||||
void removeMouseAxisBinding_(int axis);
|
||||
|
||||
protected:
|
||||
|
||||
typedef struct {
|
||||
Control::ControlChangingDirection direction;
|
||||
Control* control;
|
||||
} ControlKeyBinderItem;
|
||||
|
||||
typedef ControlKeyBinderItem ControlAxisBinderItem;
|
||||
typedef ControlKeyBinderItem ControlButtonBinderItem;
|
||||
typedef ControlKeyBinderItem ControlPOVBinderItem;
|
||||
typedef ControlKeyBinderItem ControlSliderBinderItem;
|
||||
|
||||
typedef struct {
|
||||
Control* control;
|
||||
Control::ControlChangingDirection direction;
|
||||
} PendingActionItem;
|
||||
|
||||
std::list<PendingActionItem> mPendingActions;
|
||||
|
||||
std::string mFileName;
|
||||
|
||||
typedef std::map<OIS::KeyCode, ControlKeyBinderItem> ControlsKeyBinderMapType; // <KeyCode, [direction, control]>
|
||||
typedef std::map<int, ControlAxisBinderItem> ControlsAxisBinderMapType; // <axis, [direction, control]>
|
||||
typedef std::map<int, ControlButtonBinderItem> ControlsButtonBinderMapType; // <button, [direction, control]>
|
||||
typedef std::map<int, ControlPOVBinderItem> ControlsPOVBinderMapType; // <index, [direction, control]>
|
||||
typedef std::map<int, ControlSliderBinderItem> ControlsSliderBinderMapType; // <index, [direction, control]>
|
||||
|
||||
typedef std::map<int, ControlsAxisBinderMapType> JoystickAxisBinderMapType; // <joystick_id, <axis, [direction, control]> >
|
||||
typedef std::map<int, ControlsButtonBinderMapType> JoystickButtonBinderMapType; // <joystick_id, <button, [direction, control]> >
|
||||
typedef std::map<int, std::map<int, ControlsPOVBinderMapType> > JoystickPOVBinderMapType; // <joystick_id, <index, <axis, [direction, control]> > >
|
||||
typedef std::map<int, ControlsSliderBinderMapType> JoystickSliderBinderMapType; // <joystick_id, <index, [direction, control]> >
|
||||
|
||||
ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // <axis, [direction, control]>
|
||||
ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // <int, [direction, control]>
|
||||
JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // <joystick_id, <axis, [direction, control]> >
|
||||
JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // <joystick_id, <button, [direction, control]> >
|
||||
JoystickPOVBinderMapType mControlsJoystickPOVBinderMap; // <joystick_id, <index, <axis, [direction, control]> > >
|
||||
JoystickSliderBinderMapType mControlsJoystickSliderBinderMap; // <joystick_id, <index, [direction, control]> >
|
||||
|
||||
std::vector<Control *> mControls;
|
||||
std::vector<Channel *> mChannels;
|
||||
|
||||
ControlsKeyBinderMapType mControlsKeyBinderMap;
|
||||
std::map<std::string, OIS::KeyCode> mKeys;
|
||||
std::map<OIS::KeyCode, std::string> mKeyCodes;
|
||||
|
||||
bool mActive;
|
||||
InputControlSystemLog* mLog;
|
||||
|
||||
DetectingBindingListener* mDetectingBindingListener;
|
||||
Control* mDetectingBindingControl;
|
||||
Control::ControlChangingDirection mDetectingBindingDirection;
|
||||
|
||||
bool mXmouseAxisBinded;
|
||||
bool mYmouseAxisBinded;
|
||||
|
||||
JoystickIDList mJoystickIDList;
|
||||
|
||||
int mMouseAxisBindingInitialValues[3];
|
||||
|
||||
private:
|
||||
|
||||
void fillOISKeysMap();
|
||||
};
|
||||
|
||||
class DllExport DetectingBindingListener
|
||||
{
|
||||
public:
|
||||
virtual void keyBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, OIS::KeyCode key, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void mouseAxisBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void mouseButtonBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, unsigned int button, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void joystickAxisBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int axis, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void joystickButtonBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, unsigned int button, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void joystickPOVBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction);
|
||||
|
||||
virtual void joystickSliderBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int slider, Control::ControlChangingDirection direction);
|
||||
};
|
||||
|
||||
static const float ICS_MAX = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,665 @@
|
||||
/* -------------------------------------------------------
|
||||
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
|
||||
{
|
||||
// load xml
|
||||
void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder");
|
||||
while(xmlJoystickBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlJoystickBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlJoystickBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
addJoystickAxisBinding(mControls.back(), FromString<int>(xmlJoystickBinder->Attribute("deviceId"))
|
||||
, FromString<int>(xmlJoystickBinder->Attribute("axis")), dir);
|
||||
|
||||
xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder");
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder");
|
||||
while(xmlJoystickButtonBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlJoystickButtonBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
addJoystickButtonBinding(mControls.back(), FromString<int>(xmlJoystickButtonBinder->Attribute("deviceId"))
|
||||
, FromString<int>(xmlJoystickButtonBinder->Attribute("button")), dir);
|
||||
|
||||
xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder");
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::loadJoystickPOVBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlJoystickPOVBinder = xmlControlNode->FirstChildElement("JoystickPOVBinder");
|
||||
while(xmlJoystickPOVBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
InputControlSystem::POVAxis axis = /*POVAxis::*/NorthSouth;
|
||||
if(std::string(xmlJoystickPOVBinder->Attribute("axis")) == "EastWest")
|
||||
{
|
||||
axis = /*POVAxis::*/EastWest;
|
||||
}
|
||||
|
||||
addJoystickPOVBinding(mControls.back(), FromString<int>(xmlJoystickPOVBinder->Attribute("deviceId"))
|
||||
, FromString<int>(xmlJoystickPOVBinder->Attribute("pov")), axis, dir);
|
||||
|
||||
xmlJoystickPOVBinder = xmlJoystickPOVBinder->NextSiblingElement("JoystickPOVBinder");
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::loadJoystickSliderBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlJoystickSliderBinder = xmlControlNode->FirstChildElement("JoystickSliderBinder");
|
||||
while(xmlJoystickSliderBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
addJoystickSliderBinding(mControls.back(), FromString<int>(xmlJoystickSliderBinder->Attribute("deviceId"))
|
||||
, FromString<int>(xmlJoystickSliderBinder->Attribute("slider")), dir);
|
||||
|
||||
xmlJoystickSliderBinder = xmlJoystickSliderBinder->NextSiblingElement("JoystickSliderBinder");
|
||||
}
|
||||
}
|
||||
|
||||
// add bindings
|
||||
void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding AxisBinder [deviceid="
|
||||
+ ToString<int>(deviceId) + ", axis="
|
||||
+ ToString<int>(axis) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlAxisBinderItem controlAxisBinderItem;
|
||||
controlAxisBinderItem.control = control;
|
||||
controlAxisBinderItem.direction = direction;
|
||||
mControlsJoystickAxisBinderMap[ deviceId ][ axis ] = controlAxisBinderItem;
|
||||
}
|
||||
|
||||
void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding JoystickButtonBinder [deviceId="
|
||||
+ ToString<int>(deviceId) + ", button="
|
||||
+ ToString<int>(button) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlButtonBinderItem controlJoystickButtonBinderItem;
|
||||
controlJoystickButtonBinderItem.direction = direction;
|
||||
controlJoystickButtonBinderItem.control = control;
|
||||
mControlsJoystickButtonBinderMap[ deviceId ][ button ] = controlJoystickButtonBinderItem;
|
||||
}
|
||||
|
||||
void InputControlSystem::addJoystickPOVBinding(Control* control, int deviceId, int index, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding JoystickPOVBinder [deviceId="
|
||||
+ ToString<int>(deviceId) + ", pov="
|
||||
+ ToString<int>(index) + ", axis="
|
||||
+ ToString<int>(axis) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlPOVBinderItem ControlPOVBinderItem;
|
||||
ControlPOVBinderItem.direction = direction;
|
||||
ControlPOVBinderItem.control = control;
|
||||
mControlsJoystickPOVBinderMap[ deviceId ][ index ][ axis ] = ControlPOVBinderItem;
|
||||
}
|
||||
|
||||
void InputControlSystem::addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding JoystickSliderBinder [deviceId="
|
||||
+ ToString<int>(deviceId) + ", direction="
|
||||
+ ToString<int>(index) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlSliderBinderItem ControlSliderBinderItem;
|
||||
ControlSliderBinderItem.direction = direction;
|
||||
ControlSliderBinderItem.control = control;
|
||||
mControlsJoystickSliderBinderMap[ deviceId ][ index ] = ControlSliderBinderItem;
|
||||
}
|
||||
|
||||
// get bindings
|
||||
int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end())
|
||||
{
|
||||
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].begin();
|
||||
while(it != mControlsJoystickAxisBinderMap[deviceId].end())
|
||||
{
|
||||
if(it->first >= 0 && it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
return /*NamedAxis::*/UNASSIGNED;
|
||||
}
|
||||
|
||||
unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].begin();
|
||||
while(it != mControlsJoystickButtonBinderMap[deviceId].end())
|
||||
{
|
||||
if(it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
return ICS_MAX_DEVICE_BUTTONS;
|
||||
}
|
||||
|
||||
InputControlSystem::POVBindingPair InputControlSystem::getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
POVBindingPair result;
|
||||
result.index = -1;
|
||||
|
||||
if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end())
|
||||
{
|
||||
//ControlsAxisBinderMapType::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin();
|
||||
std::map<int, ControlsPOVBinderMapType>::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin();
|
||||
while(it != mControlsJoystickPOVBinderMap[deviceId].end())
|
||||
{
|
||||
ControlsPOVBinderMapType::const_iterator it2 = it->second.begin();
|
||||
while(it2 != it->second.end())
|
||||
{
|
||||
if(it2->second.control == control && it2->second.direction == direction)
|
||||
{
|
||||
result.index = it->first;
|
||||
result.axis = (POVAxis)it2->first;
|
||||
return result;
|
||||
}
|
||||
it2++;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int InputControlSystem::getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].begin();
|
||||
while(it != mControlsJoystickSliderBinderMap[deviceId].end())
|
||||
{
|
||||
if(it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
return /*NamedAxis::*/UNASSIGNED;
|
||||
}
|
||||
|
||||
// remove bindings
|
||||
void InputControlSystem::removeJoystickAxisBinding(int deviceId, int axis)
|
||||
{
|
||||
if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].find(axis);
|
||||
if(it != mControlsJoystickAxisBinderMap[deviceId].end())
|
||||
{
|
||||
mControlsJoystickAxisBinderMap[deviceId].erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::removeJoystickButtonBinding(int deviceId, unsigned int button)
|
||||
{
|
||||
if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].find(button);
|
||||
if(it != mControlsJoystickButtonBinderMap[deviceId].end())
|
||||
{
|
||||
mControlsJoystickButtonBinderMap[deviceId].erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::removeJoystickPOVBinding(int deviceId, int index, POVAxis axis)
|
||||
{
|
||||
if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end())
|
||||
{
|
||||
std::map<int, ControlsPOVBinderMapType>::iterator it = mControlsJoystickPOVBinderMap[deviceId].find(index);
|
||||
if(it != mControlsJoystickPOVBinderMap[deviceId].end())
|
||||
{
|
||||
if(it->second.find(axis) != it->second.end())
|
||||
{
|
||||
mControlsJoystickPOVBinderMap[deviceId].find(index)->second.erase( it->second.find(axis) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::removeJoystickSliderBinding(int deviceId, int index)
|
||||
{
|
||||
if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].find(index);
|
||||
if(it != mControlsJoystickSliderBinderMap[deviceId].end())
|
||||
{
|
||||
mControlsJoystickSliderBinderMap[deviceId].erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// joyStick listeners
|
||||
bool InputControlSystem::buttonPressed(const OIS::JoyStickEvent &evt, int button)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
if(mControlsJoystickButtonBinderMap.find(evt.device->getID()) != mControlsJoystickButtonBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.device->getID()].find(button);
|
||||
if(it != mControlsJoystickButtonBinderMap[evt.device->getID()].end())
|
||||
{
|
||||
it->second.control->setIgnoreAutoReverse(false);
|
||||
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
|
||||
{
|
||||
it->second.control->setChangingDirection(it->second.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->second.control->getValue() == 1)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::DECREASE);
|
||||
}
|
||||
else if(it->second.control->getValue() == 0)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::INCREASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
mDetectingBindingListener->joystickButtonBindingDetected(this,
|
||||
mDetectingBindingControl, evt.device->getID(), button, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::buttonReleased(const OIS::JoyStickEvent &evt, int button)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(mControlsJoystickButtonBinderMap.find(evt.device->getID()) != mControlsJoystickButtonBinderMap.end())
|
||||
{
|
||||
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.device->getID()].find(button);
|
||||
if(it != mControlsJoystickButtonBinderMap[evt.device->getID()].end())
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::STOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::axisMoved(const OIS::JoyStickEvent &evt, int axis)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
if(mControlsJoystickAxisBinderMap.find(evt.device->getID()) != mControlsJoystickAxisBinderMap.end())
|
||||
{
|
||||
ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.device->getID() ][ axis ]; // joystic axis start at 0 index
|
||||
Control* ctrl = joystickBinderItem.control;
|
||||
if(ctrl)
|
||||
{
|
||||
ctrl->setIgnoreAutoReverse(true);
|
||||
if(joystickBinderItem.direction == Control::INCREASE)
|
||||
{
|
||||
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
|
||||
float valDisplaced = (float)( evt.state.mAxes[axis].abs - OIS::JoyStick::MIN_AXIS);
|
||||
|
||||
ctrl->setValue( valDisplaced / axisRange );
|
||||
}
|
||||
else if(joystickBinderItem.direction == Control::DECREASE)
|
||||
{
|
||||
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
|
||||
float valDisplaced = (float)(evt.state.mAxes[axis].abs - OIS::JoyStick::MIN_AXIS);
|
||||
|
||||
ctrl->setValue( 1 - ( valDisplaced / axisRange ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
//ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.device->getID() ][ axis ]; // joystic axis start at 0 index
|
||||
//Control* ctrl = joystickBinderItem.control;
|
||||
//if(ctrl && ctrl->isAxisBindable())
|
||||
if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable())
|
||||
{
|
||||
if( abs( evt.state.mAxes[axis].abs ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN)
|
||||
{
|
||||
mDetectingBindingListener->joystickAxisBindingDetected(this,
|
||||
mDetectingBindingControl, evt.device->getID(), axis, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::povMoved(const OIS::JoyStickEvent &evt, int index)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
if(mControlsJoystickPOVBinderMap.find(evt.device->getID()) != mControlsJoystickPOVBinderMap.end())
|
||||
{
|
||||
std::map<int, ControlsPOVBinderMapType>::const_iterator i = mControlsJoystickPOVBinderMap[ evt.device->getID() ].find(index);
|
||||
if(i != mControlsJoystickPOVBinderMap[ evt.device->getID() ].end())
|
||||
{
|
||||
if(evt.state.mPOV[index].direction != OIS::Pov::West
|
||||
&& evt.state.mPOV[index].direction != OIS::Pov::East
|
||||
&& evt.state.mPOV[index].direction != OIS::Pov::Centered)
|
||||
{
|
||||
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth );
|
||||
if(it != i->second.end())
|
||||
{
|
||||
it->second.control->setIgnoreAutoReverse(false);
|
||||
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
|
||||
{
|
||||
if(evt.state.mPOV[index].direction == OIS::Pov::North
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::NorthWest
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::NorthEast)
|
||||
{
|
||||
it->second.control->setChangingDirection(it->second.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->second.control->getValue() == 1)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::DECREASE);
|
||||
}
|
||||
else if(it->second.control->getValue() == 0)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::INCREASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(evt.state.mPOV[index].direction != OIS::Pov::North
|
||||
&& evt.state.mPOV[index].direction != OIS::Pov::South
|
||||
&& evt.state.mPOV[index].direction != OIS::Pov::Centered)
|
||||
{
|
||||
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/EastWest );
|
||||
if(it != i->second.end())
|
||||
{
|
||||
it->second.control->setIgnoreAutoReverse(false);
|
||||
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
|
||||
{
|
||||
if(evt.state.mPOV[index].direction == OIS::Pov::East
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::NorthEast
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::SouthEast)
|
||||
{
|
||||
it->second.control->setChangingDirection(it->second.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->second.control->getValue() == 1)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::DECREASE);
|
||||
}
|
||||
else if(it->second.control->getValue() == 0)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::INCREASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(evt.state.mPOV[index].direction == OIS::Pov::Centered)
|
||||
{
|
||||
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth );
|
||||
if(it != i->second.end())
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::STOP);
|
||||
}
|
||||
|
||||
it = i->second.find( /*POVAxis::*/EastWest );
|
||||
if(it != i->second.end())
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::STOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable())
|
||||
{
|
||||
if(evt.state.mPOV[index].direction == OIS::Pov::West
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::East
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::North
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::South)
|
||||
{
|
||||
POVAxis povAxis = NorthSouth;
|
||||
if(evt.state.mPOV[index].direction == OIS::Pov::West
|
||||
|| evt.state.mPOV[index].direction == OIS::Pov::East)
|
||||
{
|
||||
povAxis = EastWest;
|
||||
}
|
||||
|
||||
mDetectingBindingListener->joystickPOVBindingDetected(this,
|
||||
mDetectingBindingControl, evt.device->getID(), index, povAxis, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::sliderMoved(const OIS::JoyStickEvent &evt, int index)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
if(mControlsJoystickSliderBinderMap.find(evt.device->getID()) != mControlsJoystickSliderBinderMap.end())
|
||||
{
|
||||
ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ];
|
||||
Control* ctrl = joystickBinderItem.control;
|
||||
if(ctrl)
|
||||
{
|
||||
ctrl->setIgnoreAutoReverse(true);
|
||||
if(joystickBinderItem.direction == Control::INCREASE)
|
||||
{
|
||||
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
|
||||
float valDisplaced = (float)( evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS);
|
||||
|
||||
ctrl->setValue( valDisplaced / axisRange );
|
||||
}
|
||||
else if(joystickBinderItem.direction == Control::DECREASE)
|
||||
{
|
||||
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
|
||||
float valDisplaced = (float)(evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS);
|
||||
|
||||
ctrl->setValue( 1 - ( valDisplaced / axisRange ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
/*ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ];
|
||||
Control* ctrl = joystickBinderItem.control;
|
||||
if(ctrl && ctrl->isAxisBindable())
|
||||
{*/
|
||||
if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable())
|
||||
{
|
||||
if( abs( evt.state.mSliders[index].abX ) > ICS_JOYSTICK_SLIDER_BINDING_MARGIN)
|
||||
{
|
||||
mDetectingBindingListener->joystickSliderBindingDetected(this,
|
||||
mDetectingBindingControl, evt.device->getID(), index, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// joystick auto bindings
|
||||
void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the joystick axis is used by another control, remove it
|
||||
ICS->removeJoystickAxisBinding(deviceId, axis);
|
||||
|
||||
// if the control has an axis assigned, remove it
|
||||
int oldAxis = ICS->getJoystickAxisBinding(control, deviceId, direction);
|
||||
if(oldAxis != InputControlSystem::UNASSIGNED)
|
||||
{
|
||||
ICS->removeJoystickAxisBinding(deviceId, oldAxis);
|
||||
}
|
||||
|
||||
ICS->addJoystickAxisBinding(control, deviceId, axis, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, unsigned int button, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the joystick button is used by another control, remove it
|
||||
ICS->removeJoystickButtonBinding(deviceId, button);
|
||||
|
||||
// if the control has a joystick button assigned, remove it
|
||||
unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceId, direction);
|
||||
if(oldButton != ICS_MAX_DEVICE_BUTTONS)
|
||||
{
|
||||
ICS->removeJoystickButtonBinding(deviceId, oldButton);
|
||||
}
|
||||
|
||||
ICS->addJoystickButtonBinding(control, deviceId, button, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
|
||||
|
||||
void DetectingBindingListener::joystickPOVBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the joystick slider is used by another control, remove it
|
||||
ICS->removeJoystickPOVBinding(deviceId, pov, axis);
|
||||
|
||||
// if the control has a joystick button assigned, remove it
|
||||
ICS::InputControlSystem::POVBindingPair oldPOV = ICS->getJoystickPOVBinding(control, deviceId, direction);
|
||||
if(oldPOV.index >= 0 && oldPOV.axis == axis)
|
||||
{
|
||||
ICS->removeJoystickPOVBinding(deviceId, oldPOV.index, oldPOV.axis);
|
||||
}
|
||||
|
||||
ICS->addJoystickPOVBinding(control, deviceId, pov, axis, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
|
||||
void DetectingBindingListener::joystickSliderBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, int deviceId, int slider, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the joystick slider is used by another control, remove it
|
||||
ICS->removeJoystickSliderBinding(deviceId, slider);
|
||||
|
||||
// if the control has a joystick slider assigned, remove it
|
||||
int oldSlider = ICS->getJoystickSliderBinding(control, deviceId, direction);
|
||||
if(oldSlider != InputControlSystem::/*NamedAxis::*/UNASSIGNED)
|
||||
{
|
||||
ICS->removeJoystickSliderBinding(deviceId, oldSlider);
|
||||
}
|
||||
|
||||
ICS->addJoystickSliderBinding(control, deviceId, slider, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
/* -------------------------------------------------------
|
||||
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
|
||||
{
|
||||
void InputControlSystem::loadKeyBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlKeyBinder = xmlControlNode->FirstChildElement("KeyBinder");
|
||||
while(xmlKeyBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlKeyBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlKeyBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
addKeyBinding(mControls.back(), mKeys[xmlKeyBinder->Attribute("key")], dir);
|
||||
|
||||
xmlKeyBinder = xmlKeyBinder->NextSiblingElement("KeyBinder");
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::addKeyBinding(Control* control, OIS::KeyCode key, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding KeyBinder [key="
|
||||
+ keyCodeToString(key) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlKeyBinderItem controlKeyBinderItem;
|
||||
controlKeyBinderItem.control = control;
|
||||
controlKeyBinderItem.direction = direction;
|
||||
mControlsKeyBinderMap[ key ] = controlKeyBinderItem;
|
||||
}
|
||||
|
||||
void InputControlSystem::removeKeyBinding(OIS::KeyCode key)
|
||||
{
|
||||
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key);
|
||||
if(it != mControlsKeyBinderMap.end())
|
||||
{
|
||||
mControlsKeyBinderMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
OIS::KeyCode InputControlSystem::getKeyBinding(Control* control
|
||||
, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.begin();
|
||||
while(it != mControlsKeyBinderMap.end())
|
||||
{
|
||||
if(it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return OIS::KC_UNASSIGNED;
|
||||
}
|
||||
bool InputControlSystem::keyPressed(const OIS::KeyEvent &evt)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.key);
|
||||
if(it != mControlsKeyBinderMap.end())
|
||||
{
|
||||
it->second.control->setIgnoreAutoReverse(false);
|
||||
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
|
||||
{
|
||||
it->second.control->setChangingDirection(it->second.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->second.control->getValue() == 1)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::DECREASE);
|
||||
}
|
||||
else if(it->second.control->getValue() == 0)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::INCREASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
mDetectingBindingListener->keyBindingDetected(this,
|
||||
mDetectingBindingControl, evt.key, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::keyReleased(const OIS::KeyEvent &evt)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
ControlsKeyBinderMapType::const_iterator it = mControlsKeyBinderMap.find(evt.key);
|
||||
if(it != mControlsKeyBinderMap.end())
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::STOP);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DetectingBindingListener::keyBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, OIS::KeyCode key, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the key is used by another control, remove it
|
||||
ICS->removeKeyBinding(key);
|
||||
|
||||
// if the control has a key assigned, remove it
|
||||
OIS::KeyCode oldKey = ICS->getKeyBinding(control, direction);
|
||||
if(oldKey != OIS::KC_UNASSIGNED)
|
||||
{
|
||||
ICS->removeKeyBinding(oldKey);
|
||||
}
|
||||
|
||||
ICS->addKeyBinding(control, key, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,397 @@
|
||||
/* -------------------------------------------------------
|
||||
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
|
||||
{
|
||||
// load xml
|
||||
void InputControlSystem::loadMouseAxisBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlMouseBinder = xmlControlNode->FirstChildElement("MouseBinder");
|
||||
while(xmlMouseBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlMouseBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlMouseBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
NamedAxis axis = /*NamedAxis::*/ X;
|
||||
if((*xmlMouseBinder->Attribute("axis")) == 'Y')
|
||||
{
|
||||
axis = /*NamedAxis::*/ Y;
|
||||
}
|
||||
else if((*xmlMouseBinder->Attribute("axis")) == 'Z')
|
||||
{
|
||||
axis = /*NamedAxis::*/ Z;
|
||||
}
|
||||
|
||||
addMouseAxisBinding(mControls.back(), axis, dir);
|
||||
|
||||
xmlMouseBinder = xmlMouseBinder->NextSiblingElement("MouseBinder");
|
||||
}
|
||||
}
|
||||
|
||||
void InputControlSystem::loadMouseButtonBinders(TiXmlElement* xmlControlNode)
|
||||
{
|
||||
TiXmlElement* xmlMouseButtonBinder = xmlControlNode->FirstChildElement("MouseButtonBinder");
|
||||
while(xmlMouseButtonBinder)
|
||||
{
|
||||
Control::ControlChangingDirection dir = Control::STOP;
|
||||
if(std::string(xmlMouseButtonBinder->Attribute("direction")) == "INCREASE")
|
||||
{
|
||||
dir = Control::INCREASE;
|
||||
}
|
||||
else if(std::string(xmlMouseButtonBinder->Attribute("direction")) == "DECREASE")
|
||||
{
|
||||
dir = Control::DECREASE;
|
||||
}
|
||||
|
||||
int button = 0;
|
||||
if(std::string(xmlMouseButtonBinder->Attribute("button")) == "LEFT")
|
||||
{
|
||||
button = OIS::/*MouseButtonID::*/MB_Left;
|
||||
}
|
||||
else if(std::string(xmlMouseButtonBinder->Attribute("button")) == "RIGHT")
|
||||
{
|
||||
button = OIS::/*MouseButtonID::*/MB_Right;
|
||||
}
|
||||
else if(std::string(xmlMouseButtonBinder->Attribute("button")) == "MIDDLE")
|
||||
{
|
||||
button = OIS::/*MouseButtonID::*/MB_Middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = FromString<int>(xmlMouseButtonBinder->Attribute("button"));
|
||||
}
|
||||
|
||||
addMouseButtonBinding(mControls.back(), button, dir);
|
||||
|
||||
xmlMouseButtonBinder = xmlMouseButtonBinder->NextSiblingElement("MouseButtonBinder");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add bindings
|
||||
void InputControlSystem::addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
if(axis == /*NamedAxis::*/X)
|
||||
{
|
||||
mXmouseAxisBinded = true;
|
||||
}
|
||||
else if(axis == /*NamedAxis::*/Y)
|
||||
{
|
||||
mYmouseAxisBinded = true;
|
||||
}
|
||||
|
||||
addMouseAxisBinding_(control, axis, direction);
|
||||
}
|
||||
|
||||
/*protected*/ void InputControlSystem::addMouseAxisBinding_(Control* control, int axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding AxisBinder [axis="
|
||||
+ ToString<int>(axis) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlAxisBinderItem controlAxisBinderItem;
|
||||
controlAxisBinderItem.control = control;
|
||||
controlAxisBinderItem.direction = direction;
|
||||
mControlsMouseAxisBinderMap[ axis ] = controlAxisBinderItem;
|
||||
}
|
||||
|
||||
void InputControlSystem::addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction)
|
||||
{
|
||||
ICS_LOG("\tAdding MouseButtonBinder [button="
|
||||
+ ToString<int>(button) + ", direction="
|
||||
+ ToString<int>(direction) + "]");
|
||||
|
||||
ControlButtonBinderItem controlMouseButtonBinderItem;
|
||||
controlMouseButtonBinderItem.direction = direction;
|
||||
controlMouseButtonBinderItem.control = control;
|
||||
mControlsMouseButtonBinderMap[ button ] = controlMouseButtonBinderItem;
|
||||
}
|
||||
|
||||
// get bindings
|
||||
InputControlSystem::NamedAxis InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.begin();
|
||||
while(it != mControlsMouseAxisBinderMap.end())
|
||||
{
|
||||
if(it->first < 0 && it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return (InputControlSystem::NamedAxis)(it->first);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return /*NamedAxis::*/UNASSIGNED;
|
||||
}
|
||||
|
||||
//int InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction)
|
||||
//{
|
||||
// ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.begin();
|
||||
// while(it != mControlsMouseAxisBinderMap.end())
|
||||
// {
|
||||
// if(it->first >= 0 && it->second.control == control && it->second.direction == direction)
|
||||
// {
|
||||
// return it->first;
|
||||
// }
|
||||
// it++;
|
||||
// }
|
||||
|
||||
// return /*NamedAxis::*/UNASSIGNED;
|
||||
//}
|
||||
|
||||
unsigned int InputControlSystem::getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction)
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsMouseButtonBinderMap.begin();
|
||||
while(it != mControlsMouseButtonBinderMap.end())
|
||||
{
|
||||
if(it->second.control == control && it->second.direction == direction)
|
||||
{
|
||||
return it->first;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return ICS_MAX_DEVICE_BUTTONS;
|
||||
}
|
||||
|
||||
// remove bindings
|
||||
void InputControlSystem::removeMouseAxisBinding(NamedAxis axis)
|
||||
{
|
||||
if(axis == /*NamedAxis::*/X)
|
||||
{
|
||||
mXmouseAxisBinded = false;
|
||||
}
|
||||
else if(axis == /*NamedAxis::*/Y)
|
||||
{
|
||||
mYmouseAxisBinded = false;
|
||||
}
|
||||
|
||||
removeMouseAxisBinding_(axis);
|
||||
}
|
||||
/*protected*/ void InputControlSystem::removeMouseAxisBinding_(int axis)
|
||||
{
|
||||
ControlsAxisBinderMapType::iterator it = mControlsMouseAxisBinderMap.find(axis);
|
||||
if(it != mControlsMouseAxisBinderMap.end())
|
||||
{
|
||||
mControlsMouseAxisBinderMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InputControlSystem::removeMouseButtonBinding(unsigned int button)
|
||||
{
|
||||
ControlsButtonBinderMapType::iterator it = mControlsMouseButtonBinderMap.find(button);
|
||||
if(it != mControlsMouseButtonBinderMap.end())
|
||||
{
|
||||
mControlsMouseButtonBinderMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// mouse Listeners
|
||||
bool InputControlSystem::mouseMoved(const OIS::MouseEvent &evt)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
if(mXmouseAxisBinded && evt.state.X.rel)
|
||||
{
|
||||
ControlAxisBinderItem mouseBinderItem = mControlsMouseAxisBinderMap[ /*NamedAxis::*/X ];
|
||||
Control* ctrl = mouseBinderItem.control;
|
||||
ctrl->setIgnoreAutoReverse(true);
|
||||
if(mouseBinderItem.direction == Control::INCREASE)
|
||||
{
|
||||
ctrl->setValue( float( (evt.state.X.abs) / float(evt.state.width) ) );
|
||||
}
|
||||
else if(mouseBinderItem.direction == Control::DECREASE)
|
||||
{
|
||||
ctrl->setValue( 1 - float( evt.state.X.abs / float(evt.state.width) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if(mYmouseAxisBinded && evt.state.Y.rel)
|
||||
{
|
||||
ControlAxisBinderItem mouseBinderItem = mControlsMouseAxisBinderMap[ /*NamedAxis::*/Y ];
|
||||
Control* ctrl = mouseBinderItem.control;
|
||||
ctrl->setIgnoreAutoReverse(true);
|
||||
if(mouseBinderItem.direction == Control::INCREASE)
|
||||
{
|
||||
ctrl->setValue( float( (evt.state.Y.abs) / float(evt.state.height) ) );
|
||||
}
|
||||
else if(mouseBinderItem.direction == Control::DECREASE)
|
||||
{
|
||||
ctrl->setValue( 1 - float( evt.state.Y.abs / float(evt.state.height) ) );
|
||||
}
|
||||
}
|
||||
|
||||
//! @todo Whats the range of the Z axis?
|
||||
/*if(evt.state.Z.rel)
|
||||
{
|
||||
ControlAxisBinderItem mouseBinderItem = mControlsAxisBinderMap[ NamedAxis::Z ];
|
||||
Control* ctrl = mouseBinderItem.control;
|
||||
ctrl->setIgnoreAutoReverse(true);
|
||||
if(mouseBinderItem.direction == Control::INCREASE)
|
||||
{
|
||||
ctrl->setValue( float( (evt.state.Z.abs) / float(evt.state.¿width?) ) );
|
||||
}
|
||||
else if(mouseBinderItem.direction == Control::DECREASE)
|
||||
{
|
||||
ctrl->setValue( float( (1 - evt.state.Z.abs) / float(evt.state.¿width?) ) );
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
if(mDetectingBindingControl->isAxisBindable())
|
||||
{
|
||||
if(mMouseAxisBindingInitialValues[0] == ICS_MOUSE_AXIS_BINDING_NULL_VALUE)
|
||||
{
|
||||
mMouseAxisBindingInitialValues[0] = 0;
|
||||
mMouseAxisBindingInitialValues[1] = 0;
|
||||
mMouseAxisBindingInitialValues[2] = 0;
|
||||
}
|
||||
|
||||
mMouseAxisBindingInitialValues[0] += evt.state.X.rel;
|
||||
mMouseAxisBindingInitialValues[1] += evt.state.Y.rel;
|
||||
mMouseAxisBindingInitialValues[2] += evt.state.Z.rel;
|
||||
|
||||
if( abs(mMouseAxisBindingInitialValues[0]) > ICS_MOUSE_BINDING_MARGIN )
|
||||
{
|
||||
mDetectingBindingListener->mouseAxisBindingDetected(this,
|
||||
mDetectingBindingControl, X, mDetectingBindingDirection);
|
||||
}
|
||||
else if( abs(mMouseAxisBindingInitialValues[1]) > ICS_MOUSE_BINDING_MARGIN )
|
||||
{
|
||||
mDetectingBindingListener->mouseAxisBindingDetected(this,
|
||||
mDetectingBindingControl, Y, mDetectingBindingDirection);
|
||||
}
|
||||
else if( abs(mMouseAxisBindingInitialValues[2]) > ICS_MOUSE_BINDING_MARGIN )
|
||||
{
|
||||
mDetectingBindingListener->mouseAxisBindingDetected(this,
|
||||
mDetectingBindingControl, Z, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID btn)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
if(!mDetectingBindingControl)
|
||||
{
|
||||
ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn);
|
||||
if(it != mControlsMouseButtonBinderMap.end())
|
||||
{
|
||||
it->second.control->setIgnoreAutoReverse(false);
|
||||
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
|
||||
{
|
||||
it->second.control->setChangingDirection(it->second.direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->second.control->getValue() == 1)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::DECREASE);
|
||||
}
|
||||
else if(it->second.control->getValue() == 0)
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::INCREASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mDetectingBindingListener)
|
||||
{
|
||||
mDetectingBindingListener->mouseButtonBindingDetected(this,
|
||||
mDetectingBindingControl, btn, mDetectingBindingDirection);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputControlSystem::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID btn)
|
||||
{
|
||||
if(mActive)
|
||||
{
|
||||
ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn);
|
||||
if(it != mControlsMouseButtonBinderMap.end())
|
||||
{
|
||||
it->second.control->setChangingDirection(Control::STOP);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// mouse auto bindings
|
||||
void DetectingBindingListener::mouseAxisBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, InputControlSystem::NamedAxis axis, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the mouse axis is used by another control, remove it
|
||||
ICS->removeMouseAxisBinding(axis);
|
||||
|
||||
// if the control has an axis assigned, remove it
|
||||
InputControlSystem::NamedAxis oldAxis = ICS->getMouseAxisBinding(control, direction);
|
||||
if(oldAxis != InputControlSystem::UNASSIGNED)
|
||||
{
|
||||
ICS->removeMouseAxisBinding(oldAxis);
|
||||
}
|
||||
|
||||
ICS->addMouseAxisBinding(control, axis, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
|
||||
void DetectingBindingListener::mouseButtonBindingDetected(InputControlSystem* ICS, Control* control
|
||||
, unsigned int button, Control::ControlChangingDirection direction)
|
||||
{
|
||||
// if the mouse button is used by another control, remove it
|
||||
ICS->removeMouseButtonBinding(button);
|
||||
|
||||
// if the control has a mouse button assigned, remove it
|
||||
unsigned int oldButton = ICS->getMouseButtonBinding(control, direction);
|
||||
if(oldButton != ICS_MAX_DEVICE_BUTTONS)
|
||||
{
|
||||
ICS->removeMouseButtonBinding(oldButton);
|
||||
}
|
||||
|
||||
ICS->addMouseButtonBinding(control, button, direction);
|
||||
ICS->cancelDetectingBindingState();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/* -------------------------------------------------------
|
||||
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 "ICSPrerequisites.h"
|
@ -0,0 +1,111 @@
|
||||
/* -------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------- */
|
||||
|
||||
//! @todo add mouse wheel support
|
||||
|
||||
#ifndef _InputControlSystem_Prerequisites_H_
|
||||
#define _InputControlSystem_Prerequisites_H_
|
||||
|
||||
/// Include external headers
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <limits>
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
#define OIS_DYNAMIC_LIB
|
||||
#include <OIS.h>
|
||||
#include <OISMouse.h>
|
||||
#include <OISKeyboard.h>
|
||||
#include <OISJoyStick.h>
|
||||
#include <OISInputManager.h>
|
||||
|
||||
/// Define the dll export qualifier if compiling for Windows
|
||||
|
||||
/*
|
||||
#ifdef ICS_PLATFORM_WIN32
|
||||
#ifdef ICS_LIB
|
||||
#define DllExport __declspec (dllexport)
|
||||
#else
|
||||
#define DllExport __declspec (dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define DllExport
|
||||
#endif
|
||||
*/
|
||||
#define DllExport
|
||||
|
||||
// Define some macros
|
||||
#define ICS_DEPRECATED __declspec(deprecated("Deprecated. It will be removed in future versions."))
|
||||
|
||||
/// Version defines
|
||||
#define ICS_VERSION_MAJOR 0
|
||||
#define ICS_VERSION_MINOR 3
|
||||
#define ICS_VERSION_PATCH 1
|
||||
|
||||
#define ICS_MAX_DEVICE_BUTTONS 30
|
||||
|
||||
namespace ICS
|
||||
{
|
||||
template <typename T>
|
||||
bool StringIsNumber ( const std::string &Text )
|
||||
{
|
||||
std::stringstream ss(Text);
|
||||
T result;
|
||||
return ss >> result ? true : false;
|
||||
}
|
||||
|
||||
// from http://www.cplusplus.com/forum/articles/9645/
|
||||
template <typename T>
|
||||
std::string ToString ( T value )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// from http://www.cplusplus.com/forum/articles/9645/
|
||||
template <typename T>
|
||||
T FromString ( const std::string &Text )//Text not by const reference so that the function can be used with a
|
||||
{ //character array as argument
|
||||
std::stringstream ss(Text);
|
||||
T result;
|
||||
return ss >> result ? result : 0;
|
||||
}
|
||||
|
||||
class InputControlSystem;
|
||||
class Channel;
|
||||
class ChannelListener;
|
||||
class Control;
|
||||
class ControlListener;
|
||||
class DetectingBindingListener;
|
||||
class InputControlSystemLog;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#include "tinystr.h"
|
||||
|
||||
// Error value for find primitive
|
||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
|
||||
|
||||
|
||||
// Null rep.
|
||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
|
||||
|
||||
|
||||
void TiXmlString::reserve (size_type cap)
|
||||
{
|
||||
if (cap > capacity())
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(length(), cap);
|
||||
memcpy(tmp.start(), data(), length());
|
||||
swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
||||
{
|
||||
size_type cap = capacity();
|
||||
if (len > cap || cap > 3*(len + 8))
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(len);
|
||||
memcpy(tmp.start(), str, len);
|
||||
swap(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(start(), str, len);
|
||||
set_size(len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
||||
{
|
||||
size_type newsize = length() + len;
|
||||
if (newsize > capacity())
|
||||
{
|
||||
reserve (newsize + capacity());
|
||||
}
|
||||
memmove(finish(), str, len);
|
||||
set_size(newsize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.reserve(a.length() + b.length());
|
||||
tmp += a;
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
||||
tmp.reserve(a.length() + b_len);
|
||||
tmp += a;
|
||||
tmp.append(b, b_len);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
||||
tmp.reserve(a_len + b.length());
|
||||
tmp.append(a, a_len);
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
#endif // TIXML_USE_STL
|
@ -0,0 +1,319 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
|
||||
*
|
||||
* - completely rewritten. compact, clean, and fast implementation.
|
||||
* - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
|
||||
* - fixed reserve() to work as per specification.
|
||||
* - fixed buggy compares operator==(), operator<(), and operator>()
|
||||
* - fixed operator+=() to take a const ref argument, following spec.
|
||||
* - added "copy" constructor with length, and most compare operators.
|
||||
* - added swap(), clear(), size(), capacity(), operator+().
|
||||
*/
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#ifndef TIXML_STRING_INCLUDED
|
||||
#define TIXML_STRING_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The support for explicit isn't that universal, and it isn't really
|
||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
||||
used. Be nice to old compilers and macro it here:
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#else
|
||||
#define TIXML_EXPLICIT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
TiXmlString is an emulation of a subset of the std::string template.
|
||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||||
Only the member functions relevant to the TinyXML project have been implemented.
|
||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||||
*/
|
||||
class TiXmlString
|
||||
{
|
||||
public :
|
||||
// The size type used
|
||||
typedef size_t size_type;
|
||||
|
||||
// Error value for find primitive
|
||||
static const size_type npos; // = -1;
|
||||
|
||||
|
||||
// TiXmlString empty constructor
|
||||
TiXmlString () : rep_(&nullrep_)
|
||||
{
|
||||
}
|
||||
|
||||
// TiXmlString copy constructor
|
||||
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
||||
{
|
||||
init(copy.length());
|
||||
memcpy(start(), copy.data(), length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
||||
{
|
||||
init( static_cast<size_type>( strlen(copy) ));
|
||||
memcpy(start(), copy, length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
||||
{
|
||||
init(len);
|
||||
memcpy(start(), str, len);
|
||||
}
|
||||
|
||||
// TiXmlString destructor
|
||||
~TiXmlString ()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
}
|
||||
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const char * suffix)
|
||||
{
|
||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (char single)
|
||||
{
|
||||
return append(&single, 1);
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const TiXmlString & suffix)
|
||||
{
|
||||
return append(suffix.data(), suffix.length());
|
||||
}
|
||||
|
||||
|
||||
// Convert a TiXmlString into a null-terminated char *
|
||||
const char * c_str () const { return rep_->str; }
|
||||
|
||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
||||
const char * data () const { return rep_->str; }
|
||||
|
||||
// Return the length of a TiXmlString
|
||||
size_type length () const { return rep_->size; }
|
||||
|
||||
// Alias for length()
|
||||
size_type size () const { return rep_->size; }
|
||||
|
||||
// Checks if a TiXmlString is empty
|
||||
bool empty () const { return rep_->size == 0; }
|
||||
|
||||
// Return capacity of string
|
||||
size_type capacity () const { return rep_->capacity; }
|
||||
|
||||
|
||||
// single char extraction
|
||||
const char& at (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// [] operator
|
||||
char& operator [] (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// find a char in a string. Return TiXmlString::npos if not found
|
||||
size_type find (char lookup) const
|
||||
{
|
||||
return find(lookup, 0);
|
||||
}
|
||||
|
||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||||
size_type find (char tofind, size_type offset) const
|
||||
{
|
||||
if (offset >= length()) return npos;
|
||||
|
||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
//Lee:
|
||||
//The original was just too strange, though correct:
|
||||
// TiXmlString().swap(*this);
|
||||
//Instead use the quit & re-init:
|
||||
quit();
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
||||
*/
|
||||
void reserve (size_type cap);
|
||||
|
||||
TiXmlString& assign (const char* str, size_type len);
|
||||
|
||||
TiXmlString& append (const char* str, size_type len);
|
||||
|
||||
void swap (TiXmlString& other)
|
||||
{
|
||||
Rep* r = rep_;
|
||||
rep_ = other.rep_;
|
||||
other.rep_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init(size_type sz) { init(sz, sz); }
|
||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||||
char* start() const { return rep_->str; }
|
||||
char* finish() const { return rep_->str + rep_->size; }
|
||||
|
||||
struct Rep
|
||||
{
|
||||
size_type size, capacity;
|
||||
char str[1];
|
||||
};
|
||||
|
||||
void init(size_type sz, size_type cap)
|
||||
{
|
||||
if (cap)
|
||||
{
|
||||
// Lee: the original form:
|
||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||||
// doesn't work in some cases of new being overloaded. Switching
|
||||
// to the normal allocation, although use an 'int' for systems
|
||||
// that are overly picky about structure alignment.
|
||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||||
|
||||
rep_->str[ rep_->size = sz ] = '\0';
|
||||
rep_->capacity = cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
rep_ = &nullrep_;
|
||||
}
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (rep_ != &nullrep_)
|
||||
{
|
||||
// The rep_ is really an array of ints. (see the allocator, above).
|
||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||||
}
|
||||
}
|
||||
|
||||
Rep * rep_;
|
||||
static Rep nullrep_;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return ( a.length() == b.length() ) // optimization on some platforms
|
||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||||
}
|
||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||||
|
||||
|
||||
/*
|
||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||||
Only the operators that we need for TinyXML have been developped.
|
||||
*/
|
||||
class TiXmlOutStream : public TiXmlString
|
||||
{
|
||||
public :
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const char * in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif // TIXML_STRING_INCLUDED
|
||||
#endif // TIXML_USE_STL
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,53 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
// The goal of the seperate error file is to make the first
|
||||
// step towards localization. tinyxml (currently) only supports
|
||||
// english error messages, but the could now be translated.
|
||||
//
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Memory allocation failed.",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
"Error reading Attributes.",
|
||||
"Error: empty tag.",
|
||||
"Error reading end tag.",
|
||||
"Error parsing Unknown.",
|
||||
"Error parsing Comment.",
|
||||
"Error parsing Declaration.",
|
||||
"Error document empty.",
|
||||
"Error null (0) or unexpected EOF found in input stream.",
|
||||
"Error parsing CDATA.",
|
||||
"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Controller>
|
||||
<Control name="GameMenu" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="ESCAPE" direction="INCREASE" />
|
||||
<Channel number="0" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Quit" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="Q" direction="INCREASE" />
|
||||
<Channel number="1" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Screenshot" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="SYSRQ" direction="INCREASE" />
|
||||
<Channel number="2" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Inventory" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="I" direction="INCREASE" />
|
||||
<Channel number="3" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Console" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="F1" direction="INCREASE" />
|
||||
<Channel number="4" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
|
||||
<Control name="MoveLeft" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="A" direction="INCREASE" />
|
||||
<KeyBinder key="LEFT" direction="INCREASE" />
|
||||
<Channel number="5" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="MoveRight" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="D" direction="INCREASE" />
|
||||
<KeyBinder key="RIGHT" direction="INCREASE" />
|
||||
<Channel number="6" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="MoveForward" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="W" direction="INCREASE" />
|
||||
<KeyBinder key="UP" direction="INCREASE" />
|
||||
<Channel number="7" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="MoveBackward" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="S" direction="INCREASE" />
|
||||
<KeyBinder key="DOWN" direction="INCREASE" />
|
||||
<Channel number="8" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
|
||||
|
||||
<Control name="Activate" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="SPACE" direction="INCREASE" />
|
||||
<Channel number="9" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
|
||||
<Control name="Jump" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="E" direction="INCREASE" />
|
||||
<Channel number="11" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="AutoMove" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="Z" direction="INCREASE" />
|
||||
<Channel number="12" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Journal" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="J" direction="INCREASE" />
|
||||
<Channel number="14" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Sneak" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="X" direction="INCREASE" />
|
||||
<Channel number="22" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Walk" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="C" direction="INCREASE" />
|
||||
<Channel number="23" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="Crouch" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="LCONTROL" direction="INCREASE" />
|
||||
<Channel number="24" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="ReadyWeapon" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="F" direction="INCREASE" />
|
||||
<Channel number="28" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
|
||||
<Control name="ReadySpell" autoChangeDirectionOnLimitsAfterStop="false" autoReverseToInitialValue="true" initialValue="0" stepSize="MAX" stepsPerSeconds="MAX">
|
||||
<KeyBinder key="R" direction="INCREASE" />
|
||||
<Channel number="29" direction="DIRECT" percentage="1" />
|
||||
</Control>
|
||||
</Controller>
|
@ -1,3 +0,0 @@
|
||||
upload_docs.sh
|
||||
docs
|
||||
*~
|
File diff suppressed because it is too large
Load Diff
@ -1,26 +0,0 @@
|
||||
Minimal Abstraction Game Layer (Mangle) is licensed under the
|
||||
'zlib/libpng' license:
|
||||
|
||||
----
|
||||
|
||||
Copyright (c) 2009 Nicolay Korslund
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
@ -1,129 +0,0 @@
|
||||
Welcome to Mangle v0.1
|
||||
----------------------
|
||||
|
||||
Written by: Nicolay Korslund (korslund@gmail.com)
|
||||
License: zlib/png (see LICENSE.txt)
|
||||
WWW: http://asm-soft.com/mangle/
|
||||
Documentation: http://asm-soft.com/mangle/docs
|
||||
|
||||
|
||||
|
||||
Mangle is the project name for a small set of generic interfaces for
|
||||
various game middleware libraries, such as sound, input, graphics, and
|
||||
so on. You can imagine that it stands for "Minimal Abstraction Game
|
||||
Layer", if you like. It will consist of several more or less
|
||||
independent modules, one for each of these areas. These may be used
|
||||
together to build an entire game engine, or they can be used
|
||||
individually as separate libraries.
|
||||
|
||||
However, Mangle does NOT actually implement a game engine, or any new
|
||||
fundamental functionality. More on that below.
|
||||
|
||||
Currently there's modules for sound and streams / archives (virtual
|
||||
file systems.) More will come in the future (including input, 2D/3D
|
||||
graphics, GUI, physics, and more.)
|
||||
|
||||
|
||||
Main idea
|
||||
---------
|
||||
|
||||
The idea behind Mangle is to provide a uniform, consistent interface
|
||||
to other game libraries. The library does not provide ANY
|
||||
functionality on its own. Instead it connects to a backend
|
||||
implementation of your choice (or of your making.)
|
||||
|
||||
The Sound module, for example, currently has backends for OpenAL
|
||||
(output only), FFmpeg (input only) and for Audiere. Hopefully we'll
|
||||
add IrrKlang, FMod, DirectSound, Miles and more in the future. It can
|
||||
combine libraries to get more complete functionality (like using
|
||||
OpenAL for output and FFmpeg to decode sound files), and it's also
|
||||
easy to write your own backend if you're using a different (or
|
||||
home-brewed) sound system.
|
||||
|
||||
Regardless of what backend you use, the front-end interfaces (found
|
||||
eg. in sound/output.h) is identical, and as a library user you
|
||||
shouldn't notice much difference at all if you swap one backend for
|
||||
another at a later point. It should Just Work.
|
||||
|
||||
The interfaces themselves are also quite simple. Setting up a sound
|
||||
stream from FFmpeg or other decoder into OpenAL can be quite hairy -
|
||||
but with Mangle the hairy parts have already been written for you. You
|
||||
just plug the parts together.
|
||||
|
||||
The goal in the long run is to support a wide variety of game-related
|
||||
libraries, and as many backend libraries (free and commercial) as
|
||||
possible, so that you the user will have to write as little code as
|
||||
possible.
|
||||
|
||||
|
||||
|
||||
What is it good for
|
||||
-------------------
|
||||
|
||||
The main point of Mangle, as we said above, is that it connects to any
|
||||
library of your choice "behind the scenes" but provides the same,
|
||||
super-simple interface front-end for all of them. There can benefit
|
||||
you in many ways:
|
||||
|
||||
- If you want to use a new library that Mangle support. You don't have
|
||||
to scour the net for tutorials and usage examples, since much of the
|
||||
common usage code is already included in the implementation classes.
|
||||
|
||||
- If you don't want to pollute your code with library-specific code.
|
||||
The Mangle interfaces can help you keep your code clean, and its
|
||||
user interface is often simpler than the exteral library one.
|
||||
|
||||
- If you want to quickly connect different libraries together, it
|
||||
really helps if they speak a common language. The Mangle interfaces
|
||||
are exactly that - a common language between libraries. Do you need
|
||||
Audiere to load sounds from a weird archive format only implemented
|
||||
for PhysFS, all channeled through the OGRE resource system? No
|
||||
problem!
|
||||
|
||||
- If you are creating a library that depends on a specific feature
|
||||
(such as sound), but you don't want to lock your users into any
|
||||
specific sound library. Mangle works as an abstraction that lets
|
||||
your users select their own implementation.
|
||||
|
||||
- If you want to support multiple backends for your game/app, or want
|
||||
to make it possible to easily switch backends later. You can select
|
||||
backends at compile time or even at runtime. For example you might
|
||||
want to switch to to a commercial sound library at a later stage in
|
||||
development, or you may want to use a different input library on
|
||||
console platforms than on PC.
|
||||
|
||||
The Mangle implementations are extremely light-weight - often just one
|
||||
or two cpp/h pairs per module. You can plug them directly into your
|
||||
program, there's no separate library building step required.
|
||||
|
||||
Since the library aims to be very modularly put together, you can
|
||||
also, in many cases, just copy-and-paste the parts you need and ignore
|
||||
the rest. Or modify stuff without fearing that the whole 'system' will
|
||||
come crashing down, because there is no big 'system' to speak of.
|
||||
|
||||
|
||||
Past and future
|
||||
---------------
|
||||
|
||||
Mangle started out as (and still is) a spin-off from OpenMW, another
|
||||
project I am personally working on ( http://openmw.com/ ). OpenMW is
|
||||
an attempt to recreate the engine behind the commercial game
|
||||
Morrowind, using only open source software.
|
||||
|
||||
The projects are still tightly interlinked, and they will continue to
|
||||
be until OpenMW is finished. Most near-future work on Mangle will be
|
||||
focused chiefly on OpenMW at the moment. However I will gladly include
|
||||
external contributions and suggestions that are not OpenMW-related if
|
||||
someone sends them to me.
|
||||
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
As you might have guessed, Mangle is more a concept in development
|
||||
than a finished library right now.
|
||||
|
||||
All feedback, ideas, concepts, questions and code are very
|
||||
welcome. Send them to: korslund@gmail.com
|
||||
|
||||
I will put up a forum later as well if there's enough interest.
|
@ -1,29 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_OGREINPUTFRAME_H
|
||||
#define MANGLE_INPUT_OGREINPUTFRAME_H
|
||||
|
||||
/*
|
||||
This Ogre FrameListener calls capture() on an input driver every frame.
|
||||
*/
|
||||
|
||||
#include <OgreFrameListener.h>
|
||||
#include "../driver.hpp"
|
||||
|
||||
namespace Mangle {
|
||||
namespace Input {
|
||||
|
||||
struct OgreInputCapture : Ogre::FrameListener
|
||||
{
|
||||
Mangle::Input::Driver &driver;
|
||||
|
||||
OgreInputCapture(Mangle::Input::Driver &drv)
|
||||
: driver(drv) {}
|
||||
|
||||
bool frameStarted(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
driver.capture();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
@ -1,69 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_DRIVER_H
|
||||
#define MANGLE_INPUT_DRIVER_H
|
||||
|
||||
#include "event.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** Input::Driver is the main interface to any input system that
|
||||
handles keyboard and/or mouse input, along with any other
|
||||
input source like joysticks.
|
||||
|
||||
It is really a generalized event system, and could also be
|
||||
used for non-input related events. The definition of the event
|
||||
codes and structures are entirely dependent on the
|
||||
implementation.
|
||||
|
||||
A system-independent key code list will be found in keys.hpp,
|
||||
and input drivers should privide optional translations to/from
|
||||
this list for full compatibility.
|
||||
*/
|
||||
struct Driver
|
||||
{
|
||||
Driver() {}
|
||||
virtual ~Driver() {}
|
||||
|
||||
/** Captures input and produces the relevant events from it. An
|
||||
event callback must be set with setEvent(), or all events
|
||||
will be ignored.
|
||||
*/
|
||||
virtual void capture() = 0;
|
||||
|
||||
/** Check the state of a given key or button. The key/button
|
||||
definitions depends on the driver.
|
||||
*/
|
||||
virtual bool isDown(int index) = 0;
|
||||
|
||||
/** Show or hide system mouse cursor
|
||||
*/
|
||||
virtual void showMouse(bool show) = 0;
|
||||
|
||||
/** Set the event handler for input events. The evt->event()
|
||||
function is called for each event. The meaning of the index
|
||||
and *p parameters will be specific to each driver and to
|
||||
each input system.
|
||||
*/
|
||||
void setEvent(EventPtr evt)
|
||||
{ event = evt; }
|
||||
|
||||
/** Instigate an event. Is used internally for all events, but
|
||||
can also be called from the outside to "fake" events from
|
||||
this driver.
|
||||
*/
|
||||
void makeEvent(Event::Type type, int index, const void *p=NULL)
|
||||
{
|
||||
if(event)
|
||||
event->event(type,index,p);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Holds the event callback set byt setEvent()
|
||||
EventPtr event;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Driver> DriverPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_EVENT_H
|
||||
#define MANGLE_INPUT_EVENT_H
|
||||
|
||||
#include "../tools/shared_ptr.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** Generic callback for input events. The meaning of the
|
||||
parameters depend on the system producing the events.
|
||||
*/
|
||||
struct Event
|
||||
{
|
||||
/// Event types
|
||||
enum Type
|
||||
{
|
||||
EV_Unknown = 1, // Unknown event type
|
||||
EV_KeyDown = 2, // Keyboard button was pressed
|
||||
EV_KeyUp = 4, // Keyboard button was released
|
||||
EV_Keyboard = 6, // All keyboard events
|
||||
|
||||
EV_MouseMove = 8, // Mouse movement
|
||||
EV_MouseDown = 16, // Mouse button pressed
|
||||
EV_MouseUp = 32, // Mouse button released
|
||||
EV_Mouse = 56, // All mouse events
|
||||
|
||||
EV_ALL = 63 // All events
|
||||
};
|
||||
|
||||
/**
|
||||
Called upon all events. The first parameter give the event
|
||||
type, the second gives additional data (usually the local
|
||||
keysym or button index as defined by the driver), and the
|
||||
pointer points to the full custom event structure provided by
|
||||
the driver (the type may vary depending on the EventType,
|
||||
this is defined in the Driver documentation.)
|
||||
*/
|
||||
virtual void event(Type type, int index, const void *p) = 0;
|
||||
virtual ~Event() {}
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Event> EventPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_EVENTLIST_H
|
||||
#define MANGLE_INPUT_EVENTLIST_H
|
||||
|
||||
#include "../event.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** And Event handler that distributes each event to a list of
|
||||
other handlers. Supports filtering events by their Type
|
||||
parameter.
|
||||
*/
|
||||
struct EventList : Event
|
||||
{
|
||||
struct Filter
|
||||
{
|
||||
EventPtr evt;
|
||||
int flags;
|
||||
};
|
||||
std::vector<Filter> list;
|
||||
|
||||
void add(EventPtr e, int flags = EV_ALL)
|
||||
{
|
||||
Filter f;
|
||||
f.evt = e;
|
||||
f.flags = flags;
|
||||
list.push_back(f);
|
||||
}
|
||||
|
||||
virtual void event(Type type, int index, const void *p)
|
||||
{
|
||||
std::vector<Filter>::iterator it;
|
||||
|
||||
for(it=list.begin(); it!=list.end(); it++)
|
||||
{
|
||||
if(type & it->flags)
|
||||
it->evt->event(type,index,p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<EventList> EventListPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,154 +0,0 @@
|
||||
#include "ois_driver.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OIS/OIS.h>
|
||||
|
||||
#ifdef __APPLE_CC__
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
using namespace Mangle::Input;
|
||||
using namespace OIS;
|
||||
|
||||
struct Mangle::Input::OISListener : OIS::KeyListener, OIS::MouseListener
|
||||
{
|
||||
OISDriver &drv;
|
||||
|
||||
OISListener(OISDriver &driver)
|
||||
: drv(driver) {}
|
||||
|
||||
bool keyPressed( const OIS::KeyEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_KeyDown, arg.key, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool keyReleased( const OIS::KeyEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_KeyUp, arg.key, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
|
||||
{
|
||||
// Mouse button events are handled as key events
|
||||
// TODO: Translate mouse buttons into pseudo-keysyms
|
||||
drv.makeEvent(Event::EV_MouseDown, id, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
|
||||
{
|
||||
// TODO: ditto
|
||||
drv.makeEvent(Event::EV_MouseUp, id, &arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mouseMoved( const OIS::MouseEvent &arg )
|
||||
{
|
||||
drv.makeEvent(Event::EV_MouseMove, -1, &arg);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
OISDriver::OISDriver(Ogre::RenderWindow *window, bool exclusive)
|
||||
{
|
||||
assert(window);
|
||||
|
||||
size_t windowHnd;
|
||||
|
||||
window->getCustomAttribute("WINDOW", &windowHnd);
|
||||
|
||||
std::ostringstream windowHndStr;
|
||||
ParamList pl;
|
||||
|
||||
windowHndStr << windowHnd;
|
||||
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
|
||||
|
||||
// Set non-exclusive mouse and keyboard input if the user requested
|
||||
// it.
|
||||
if(!exclusive)
|
||||
{
|
||||
#if defined OIS_WIN32_PLATFORM
|
||||
pl.insert(std::make_pair(std::string("w32_mouse"),
|
||||
std::string("DISCL_FOREGROUND" )));
|
||||
pl.insert(std::make_pair(std::string("w32_mouse"),
|
||||
std::string("DISCL_NONEXCLUSIVE")));
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"),
|
||||
std::string("DISCL_FOREGROUND")));
|
||||
pl.insert(std::make_pair(std::string("w32_keyboard"),
|
||||
std::string("DISCL_NONEXCLUSIVE")));
|
||||
#elif defined OIS_LINUX_PLATFORM
|
||||
pl.insert(std::make_pair(std::string("x11_mouse_grab"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("x11_mouse_hide"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("x11_keyboard_grab"),
|
||||
std::string("false")));
|
||||
pl.insert(std::make_pair(std::string("XAutoRepeatOn"),
|
||||
std::string("true")));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE_CC__
|
||||
// Give the application window focus to receive input events
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
#endif
|
||||
|
||||
inputMgr = InputManager::createInputSystem( pl );
|
||||
|
||||
// Create all devices
|
||||
keyboard = static_cast<Keyboard*>(inputMgr->createInputObject
|
||||
( OISKeyboard, true ));
|
||||
mouse = static_cast<Mouse*>(inputMgr->createInputObject
|
||||
( OISMouse, true ));
|
||||
|
||||
// Set mouse region
|
||||
const MouseState &ms = mouse->getMouseState();
|
||||
ms.width = window->getWidth();
|
||||
ms.height = window->getHeight();
|
||||
|
||||
// Set up the input listener
|
||||
listener = new OISListener(*this);
|
||||
keyboard-> setEventCallback(listener);
|
||||
mouse-> setEventCallback(listener);
|
||||
}
|
||||
|
||||
OISDriver::~OISDriver()
|
||||
{
|
||||
// Delete the listener object
|
||||
delete listener;
|
||||
|
||||
if(inputMgr == NULL) return;
|
||||
|
||||
// Kill the input systems. This will reset input options such as key
|
||||
// repeat rate.
|
||||
inputMgr->destroyInputObject(keyboard);
|
||||
inputMgr->destroyInputObject(mouse);
|
||||
InputManager::destroyInputSystem(inputMgr);
|
||||
inputMgr = NULL;
|
||||
}
|
||||
|
||||
void OISDriver::capture()
|
||||
{
|
||||
// Capture keyboard and mouse events
|
||||
keyboard->capture();
|
||||
mouse->capture();
|
||||
}
|
||||
|
||||
bool OISDriver::isDown(int index)
|
||||
{
|
||||
// TODO: Extend to mouse buttons as well
|
||||
return keyboard->isKeyDown((OIS::KeyCode)index);
|
||||
}
|
||||
|
||||
void OISDriver::adjustMouseClippingSize(int width, int height)
|
||||
{
|
||||
const OIS::MouseState &ms = mouse->getMouseState();
|
||||
ms.width = width;
|
||||
ms.height = height;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_OIS_DRIVER_H
|
||||
#define MANGLE_INPUT_OIS_DRIVER_H
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
namespace OIS
|
||||
{
|
||||
class InputManager;
|
||||
class Mouse;
|
||||
class Keyboard;
|
||||
}
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class RenderWindow;
|
||||
}
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
struct OISListener;
|
||||
|
||||
/** Input driver for OIS, the input manager typically used with
|
||||
Ogre.
|
||||
*/
|
||||
struct OISDriver : Driver
|
||||
{
|
||||
/// If exclusive=true, then we capture mouse and keyboard from
|
||||
/// the OS.
|
||||
OISDriver(Ogre::RenderWindow *window, bool exclusive=true);
|
||||
~OISDriver();
|
||||
|
||||
void adjustMouseClippingSize(int width, int height);
|
||||
|
||||
void capture();
|
||||
bool isDown(int index);
|
||||
/// Not currently supported.
|
||||
void showMouse(bool) {}
|
||||
|
||||
private:
|
||||
OIS::InputManager *inputMgr;
|
||||
OIS::Mouse *mouse;
|
||||
OIS::Keyboard *keyboard;
|
||||
|
||||
OISListener *listener;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
#include "sdl_driver.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
using namespace Mangle::Input;
|
||||
|
||||
void SDLDriver::capture()
|
||||
{
|
||||
// Poll for events
|
||||
SDL_Event evt;
|
||||
while(SDL_PollEvent(&evt))
|
||||
{
|
||||
Event::Type type = Event::EV_Unknown;
|
||||
int index = -1;
|
||||
|
||||
switch(evt.type)
|
||||
{
|
||||
// For key events, send the keysym as the index.
|
||||
case SDL_KEYDOWN:
|
||||
type = Event::EV_KeyDown;
|
||||
index = evt.key.keysym.sym;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
type = Event::EV_KeyUp;
|
||||
index = evt.key.keysym.sym;
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
type = Event::EV_MouseMove;
|
||||
break;
|
||||
// Add more event types later
|
||||
}
|
||||
|
||||
// Pass the event along, using -1 as index for unidentified
|
||||
// event types.
|
||||
makeEvent(type, index, &evt);
|
||||
}
|
||||
}
|
||||
|
||||
bool SDLDriver::isDown(int index)
|
||||
{
|
||||
int num;
|
||||
Uint8 *keys = SDL_GetKeyState(&num);
|
||||
assert(index >= 0 && index < num);
|
||||
|
||||
// The returned array from GetKeyState is indexed by the
|
||||
// SDLK_KEYNAME enums and is just a list of bools. If the indexed
|
||||
// value is true, the button is down.
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
void SDLDriver::showMouse(bool show)
|
||||
{
|
||||
SDL_ShowCursor(show?SDL_ENABLE:SDL_DISABLE);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#ifndef MANGLE_INPUT_SDL_DRIVER_H
|
||||
#define MANGLE_INPUT_SDL_DRIVER_H
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
/** Input driver for SDL. As the input system of SDL is seldomly
|
||||
used alone (most often along with the video system), it is
|
||||
assumed that you do your own initialization and cleanup of SDL
|
||||
before and after using this driver.
|
||||
|
||||
The Event.event() calls will be given the proper EV_ type, the
|
||||
key index (for key up/down events), and a pointer to the full
|
||||
SDL_Event structure.
|
||||
*/
|
||||
struct SDLDriver : Driver
|
||||
{
|
||||
void capture();
|
||||
bool isDown(int index);
|
||||
void showMouse(bool);
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,2 +0,0 @@
|
||||
*_test
|
||||
ogre.cfg
|
@ -1,15 +0,0 @@
|
||||
GCC=g++ -Wall
|
||||
|
||||
all: sdl_driver_test ois_driver_test evtlist_test
|
||||
|
||||
sdl_driver_test: sdl_driver_test.cpp
|
||||
$(GCC) $< ../servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL
|
||||
|
||||
ois_driver_test: ois_driver_test.cpp
|
||||
$(GCC) $< ../servers/ois_driver.cpp -o $@ -I/usr/local/include/OGRE/ -lOgreMain -lOIS -lboost_filesystem
|
||||
|
||||
evtlist_test: evtlist_test.cpp ../filters/eventlist.hpp ../event.hpp
|
||||
$(GCC) $< -o $@
|
||||
|
||||
clean:
|
||||
rm *_test
|
@ -1,35 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "../driver.hpp"
|
||||
#include <unistd.h>
|
||||
using namespace std;
|
||||
using namespace Mangle::Input;
|
||||
|
||||
Driver *input;
|
||||
|
||||
struct MyCB : Event
|
||||
{
|
||||
void event(Event::Type type, int i, const void *p)
|
||||
{
|
||||
cout << "got event: type=" << type << " index=" << i << endl;
|
||||
}
|
||||
};
|
||||
|
||||
void mainLoop(int argc, int quitKey)
|
||||
{
|
||||
cout << "Hold the Q key to quit:\n";
|
||||
input->setEvent(EventPtr(new MyCB));
|
||||
while(!input->isDown(quitKey))
|
||||
{
|
||||
input->capture();
|
||||
usleep(20000);
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
cout << "You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete input;
|
||||
cout << "\nBye bye!\n";
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "../filters/eventlist.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace Mangle::Input;
|
||||
|
||||
struct MyEvent : Event
|
||||
{
|
||||
int ii;
|
||||
MyEvent(int i) : ii(i) {}
|
||||
|
||||
void event(Event::Type type, int i, const void *p)
|
||||
{
|
||||
cout << " #" << ii << " got event: type=" << type << " index=" << i << endl;
|
||||
}
|
||||
};
|
||||
|
||||
EventList lst;
|
||||
|
||||
int iii=1;
|
||||
void make(int flags)
|
||||
{
|
||||
lst.add(EventPtr(new MyEvent(iii++)), flags);
|
||||
}
|
||||
|
||||
void send(Event::Type type)
|
||||
{
|
||||
cout << "Sending type " << type << endl;
|
||||
lst.event(type,0,NULL);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
make(Event::EV_ALL);
|
||||
make(Event::EV_KeyDown);
|
||||
make(Event::EV_KeyUp | Event::EV_MouseDown);
|
||||
|
||||
send(Event::EV_Unknown);
|
||||
send(Event::EV_KeyDown);
|
||||
send(Event::EV_KeyUp);
|
||||
send(Event::EV_MouseDown);
|
||||
|
||||
cout << "Enough of that\n";
|
||||
return 0;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
#include "common.cpp"
|
||||
|
||||
#include "../servers/ois_driver.hpp"
|
||||
#include <Ogre.h>
|
||||
#include <OIS/OIS.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
bool isFile(const char *name)
|
||||
{
|
||||
boost::filesystem::path cfg_file_path(name);
|
||||
return boost::filesystem::exists(cfg_file_path);
|
||||
}
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace OIS;
|
||||
|
||||
Root *root;
|
||||
RenderWindow *window;
|
||||
|
||||
void setupOgre()
|
||||
{
|
||||
// Disable logging
|
||||
new LogManager;
|
||||
Log *log = LogManager::getSingleton().createLog("");
|
||||
log->setDebugOutputEnabled(false);
|
||||
|
||||
bool useConfig = isFile("ogre.cfg");
|
||||
|
||||
// Set up Root
|
||||
root = new Root("plugins.cfg", "ogre.cfg", "");
|
||||
|
||||
// Configure
|
||||
if(!useConfig)
|
||||
root->showConfigDialog();
|
||||
else
|
||||
root->restoreConfig();
|
||||
|
||||
// Initialize OGRE window
|
||||
window = root->initialise(true, "test", "");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
setupOgre();
|
||||
input = new OISDriver(window);
|
||||
|
||||
mainLoop(argc, KC_Q);
|
||||
|
||||
delete root;
|
||||
return 0;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
Sending type 1
|
||||
#1 got event: type=1 index=0
|
||||
Sending type 2
|
||||
#1 got event: type=2 index=0
|
||||
#2 got event: type=2 index=0
|
||||
Sending type 4
|
||||
#1 got event: type=4 index=0
|
||||
#3 got event: type=4 index=0
|
||||
Sending type 16
|
||||
#1 got event: type=16 index=0
|
||||
#3 got event: type=16 index=0
|
||||
Enough of that
|
@ -1,5 +0,0 @@
|
||||
Hold the Q key to quit:
|
||||
got event: type=8 index=-1
|
||||
You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly
|
||||
|
||||
Bye bye!
|
@ -1,5 +0,0 @@
|
||||
Hold the Q key to quit:
|
||||
got event: type=1 index=-1
|
||||
You are running in script mode, aborting. Run this test with a parameter (any at all) to test the input loop properly
|
||||
|
||||
Bye bye!
|
@ -1,12 +0,0 @@
|
||||
# Defines plugins to load
|
||||
|
||||
# Define plugin folder
|
||||
PluginFolder=/usr/local/lib/OGRE/
|
||||
|
||||
# Define plugins
|
||||
Plugin=RenderSystem_GL
|
||||
Plugin=Plugin_ParticleFX
|
||||
Plugin=Plugin_OctreeSceneManager
|
||||
# Plugin=Plugin_CgProgramManager
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "common.cpp"
|
||||
|
||||
#include "../servers/sdl_driver.hpp"
|
||||
#include <SDL.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE);
|
||||
input = new SDLDriver();
|
||||
|
||||
mainLoop(argc, SDLK_q);
|
||||
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
make || exit
|
||||
|
||||
mkdir -p output
|
||||
|
||||
PROGS=*_test
|
||||
|
||||
for a in $PROGS; do
|
||||
if [ -f "output/$a.out" ]; then
|
||||
echo "Running $a:"
|
||||
./$a | diff output/$a.out -
|
||||
else
|
||||
echo "Creating $a.out"
|
||||
./$a > "output/$a.out"
|
||||
git add "output/$a.out"
|
||||
fi
|
||||
done
|
@ -1,63 +0,0 @@
|
||||
#ifndef MANGLE_REND2D_DRIVER_H
|
||||
#define MANGLE_REND2D_DRIVER_H
|
||||
|
||||
#include <string>
|
||||
#include "sprite.hpp"
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Rend2D
|
||||
{
|
||||
/**
|
||||
The driver is the connection to the backend system that powers
|
||||
2D sprite rendering. For example the backend could be SDL or
|
||||
any other 2D-capable graphics library.
|
||||
*/
|
||||
struct Driver
|
||||
{
|
||||
/// Get the screen sprite
|
||||
virtual Sprite *getScreen() = 0;
|
||||
|
||||
/// Sets the video mode.
|
||||
virtual void setVideoMode(int width, int height, int bpp=32, bool fullscreen=false) = 0;
|
||||
|
||||
/** Update the screen. Until this function is called, none of
|
||||
the changes written to the screen sprite will be visible.
|
||||
*/
|
||||
virtual void update() = 0;
|
||||
|
||||
/// Set the window title, as well as the title of the window
|
||||
/// when "iconified"
|
||||
virtual void setWindowTitle(const std::string &title,
|
||||
const std::string &icon) = 0;
|
||||
|
||||
/// Set the window title
|
||||
void setWindowTitle(const std::string &title) { setWindowTitle(title,title); }
|
||||
|
||||
/// Load sprite from an image file. Thows an exception on
|
||||
/// failure.
|
||||
virtual Sprite* loadImage(const std::string &file) = 0;
|
||||
|
||||
/// Load a sprite from an image file stored in memory. Throws
|
||||
/// exception on failure.
|
||||
virtual Sprite* loadImage(const void* data, size_t size) = 0;
|
||||
|
||||
/** @brief Set gamma value for all colors.
|
||||
|
||||
Note: Setting this in windowed mode will affect the ENTIRE
|
||||
SCREEN!
|
||||
*/
|
||||
virtual void setGamma(float gamma) = 0;
|
||||
|
||||
/// Set gamma individually for red, green, blue
|
||||
virtual void setGamma(float red, float green, float blue) = 0;
|
||||
|
||||
/// Get screen width
|
||||
virtual int width() = 0;
|
||||
|
||||
/// Get screen height
|
||||
virtual int height() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,259 +0,0 @@
|
||||
#include "sdl_driver.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
using namespace Mangle::Rend2D;
|
||||
|
||||
const SpriteData *SDL_Sprite::lock()
|
||||
{
|
||||
// Make sure we aren't already locked
|
||||
assert(!data.pixels);
|
||||
|
||||
// Lock the surface and set up the data structure
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
data.pixels = surface->pixels;
|
||||
data.w = surface->w;
|
||||
data.h = surface->h;
|
||||
data.pitch = surface->pitch;
|
||||
data.bypp = surface->format->BytesPerPixel;
|
||||
|
||||
return &data;
|
||||
}
|
||||
|
||||
void SDL_Sprite::unlock()
|
||||
{
|
||||
if(data.pixels)
|
||||
{
|
||||
SDL_UnlockSurface(surface);
|
||||
data.pixels = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a really crappy and slow implementation, only intended for
|
||||
// testing purposes. Use lock/unlock for faster pixel drawing.
|
||||
void SDL_Sprite::pixel(int x, int y, int color)
|
||||
{
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
char *p = (char*)surface->pixels + y*surface->pitch + x*bpp;
|
||||
|
||||
switch(bpp)
|
||||
{
|
||||
case 1: *p = color; break;
|
||||
case 3:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
{
|
||||
p[0] = (color >> 16) & 0xff;
|
||||
p[1] = (color >> 8) & 0xff;
|
||||
p[2] = color & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
p[0] = color & 0xff;
|
||||
p[1] = (color >> 8) & 0xff;
|
||||
p[2] = (color >> 16) & 0xff;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
*(int*)p = color;
|
||||
break;
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
void SDL_Sprite::draw(Sprite *s, // Must be SDL_Sprite
|
||||
int x, int y, // Destination position
|
||||
int sx, int sy, // Source position
|
||||
int w, int h // Amount to draw. -1 means remainder.
|
||||
)
|
||||
{
|
||||
// Get source surface
|
||||
SDL_Sprite *other = dynamic_cast<SDL_Sprite*>(s);
|
||||
assert(other != NULL);
|
||||
SDL_Surface *img = other->getSurface();
|
||||
|
||||
// Check coordinate validity
|
||||
assert(sx <= img->w && sy <= img->h);
|
||||
assert(x <= surface->w && y <= surface->h);
|
||||
assert(sx >= 0 && sy >= 0);
|
||||
|
||||
// Compute width and height if necessary
|
||||
if(w == -1) w = img->w - sx;
|
||||
if(h == -1) h = img->h - sy;
|
||||
|
||||
// Check them if they're valid
|
||||
assert(w >= 0 && w <= img->w);
|
||||
assert(h >= 0 && h <= img->h);
|
||||
|
||||
SDL_Rect dest;
|
||||
dest.x = x;
|
||||
dest.y = y;
|
||||
dest.w = w;
|
||||
dest.h = h;
|
||||
|
||||
SDL_Rect src;
|
||||
src.x = sx;
|
||||
src.y = sy;
|
||||
src.w = w;
|
||||
src.h = h;
|
||||
|
||||
// Do the Blitman
|
||||
SDL_BlitSurface(img, &src, surface, &dest);
|
||||
}
|
||||
|
||||
SDL_Sprite::SDL_Sprite(SDL_Surface *s, bool autoDelete)
|
||||
: surface(s), autoDel(autoDelete)
|
||||
{
|
||||
assert(surface != NULL);
|
||||
data.pixels = NULL;
|
||||
}
|
||||
|
||||
SDL_Sprite::~SDL_Sprite()
|
||||
{
|
||||
if(autoDel)
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
void SDL_Sprite::fill(int value)
|
||||
{
|
||||
SDL_FillRect(surface, NULL, value);
|
||||
}
|
||||
|
||||
int SDL_Sprite::width() { return surface->w; }
|
||||
int SDL_Sprite::height() { return surface->h; }
|
||||
|
||||
SDLDriver::SDLDriver() : display(NULL), realDisp(NULL), softDouble(false)
|
||||
{
|
||||
if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1)
|
||||
throw std::runtime_error("Error initializing SDL video");
|
||||
}
|
||||
SDLDriver::~SDLDriver()
|
||||
{
|
||||
if(display) delete display;
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void SDLDriver::setVideoMode(int width, int height, int bpp, bool fullscreen)
|
||||
{
|
||||
unsigned int flags;
|
||||
|
||||
if(display) delete display;
|
||||
|
||||
if (fullscreen)
|
||||
// Assume fullscreen mode allows a double-bufferd hardware
|
||||
// mode. We need more test code for this to be safe though.
|
||||
flags = SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF;
|
||||
else
|
||||
flags = SDL_SWSURFACE;
|
||||
|
||||
// Create the surface and check it
|
||||
realDisp = SDL_SetVideoMode(width, height, bpp, flags);
|
||||
if(realDisp == NULL)
|
||||
throw std::runtime_error("Failed setting SDL video mode");
|
||||
|
||||
// Code for software double buffering. I haven't found this to be
|
||||
// any speed advantage at all in windowed mode (it's slower, as one
|
||||
// would expect.) Not properly tested in fullscreen mode with
|
||||
// hardware buffers, but it will probably only be an improvement if
|
||||
// we do excessive writing (ie. write each pixel on average more
|
||||
// than once) or try to read from the display buffer.
|
||||
if(softDouble)
|
||||
{
|
||||
// Make a new surface with the same attributes as the real
|
||||
// display surface.
|
||||
SDL_Surface *back = SDL_DisplayFormat(realDisp);
|
||||
assert(back != NULL);
|
||||
|
||||
// Create a sprite representing the double buffer
|
||||
display = new SDL_Sprite(back);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a sprite directly representing the display surface.
|
||||
// The 'false' parameter means do not autodelete the screen
|
||||
// surface upon exit (since SDL manages it)
|
||||
display = new SDL_Sprite(realDisp, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the screen
|
||||
void SDLDriver::update()
|
||||
{
|
||||
// Blit the soft double buffer onto the real display buffer
|
||||
if(softDouble)
|
||||
SDL_BlitSurface(display->getSurface(), NULL, realDisp, NULL );
|
||||
|
||||
if(realDisp)
|
||||
SDL_Flip(realDisp);
|
||||
}
|
||||
|
||||
/// Set the window title, as well as the title of the window when
|
||||
/// "iconified"
|
||||
void SDLDriver::setWindowTitle(const std::string &title,
|
||||
const std::string &icon)
|
||||
{
|
||||
SDL_WM_SetCaption( title.c_str(), icon.c_str() );
|
||||
}
|
||||
|
||||
// Convert the given surface to display format.
|
||||
static SDL_Surface* convertImage(SDL_Surface* surf)
|
||||
{
|
||||
if(surf != NULL)
|
||||
{
|
||||
// Convert the image to the display buffer format, for faster
|
||||
// blitting
|
||||
SDL_Surface *surf2 = SDL_DisplayFormat(surf);
|
||||
SDL_FreeSurface(surf);
|
||||
surf = surf2;
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
|
||||
/// Load sprite from an image file, using SDL_image.
|
||||
Sprite* SDLDriver::loadImage(const std::string &file)
|
||||
{
|
||||
SDL_Surface *surf = IMG_Load(file.c_str());
|
||||
surf = convertImage(surf);
|
||||
if(surf == NULL)
|
||||
throw std::runtime_error("SDL failed to load image file '" + file + "'");
|
||||
return spriteFromSDL(surf);
|
||||
}
|
||||
|
||||
/// Load sprite from an SDL_RWops structure. autoFree determines
|
||||
/// whether the RWops struct should be closed/freed after use.
|
||||
Sprite* SDLDriver::loadImage(SDL_RWops *src, bool autoFree)
|
||||
{
|
||||
SDL_Surface *surf = IMG_Load_RW(src, autoFree);
|
||||
surf = convertImage(surf);
|
||||
if(surf == NULL)
|
||||
throw std::runtime_error("SDL failed to load image");
|
||||
return spriteFromSDL(surf);
|
||||
}
|
||||
|
||||
/// Load a sprite from an image file stored in memory. Uses
|
||||
/// SDL_image.
|
||||
Sprite* SDLDriver::loadImage(const void* data, size_t size)
|
||||
{
|
||||
SDL_RWops *rw = SDL_RWFromConstMem(data, size);
|
||||
return loadImage(rw, true);
|
||||
}
|
||||
|
||||
void SDLDriver::setGamma(float red, float green, float blue)
|
||||
{
|
||||
SDL_SetGamma(red,green,blue);
|
||||
}
|
||||
|
||||
/// Convert an existing SDL surface into a sprite
|
||||
Sprite* SDLDriver::spriteFromSDL(SDL_Surface *surf, bool autoFree)
|
||||
{
|
||||
assert(surf);
|
||||
return new SDL_Sprite(surf, autoFree);
|
||||
}
|
||||
|
||||
void SDLDriver::sleep(int ms) { SDL_Delay(ms); }
|
||||
unsigned int SDLDriver::ticks() { return SDL_GetTicks(); }
|
@ -1,125 +0,0 @@
|
||||
#ifndef MANGLE_DRAW2D_SDL_H
|
||||
#define MANGLE_DRAW2D_SDL_H
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
// Predeclarations keep the streets safe at night
|
||||
struct SDL_Surface;
|
||||
struct SDL_RWops;
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Rend2D
|
||||
{
|
||||
/// SDL-implementation of Sprite
|
||||
struct SDL_Sprite : Sprite
|
||||
{
|
||||
/** Draw a sprite in the given position. Can only draw other SDL
|
||||
sprites.
|
||||
*/
|
||||
void draw(Sprite *s, // Must be SDL_Sprite
|
||||
int x, int y, // Destination position
|
||||
int sx=0, int sy=0, // Source position
|
||||
int w=-1, int h=-1 // Amount to draw. -1 means remainder.
|
||||
);
|
||||
|
||||
SDL_Sprite(SDL_Surface *s, bool autoDelete=true);
|
||||
~SDL_Sprite();
|
||||
|
||||
// Information retrieval
|
||||
int width();
|
||||
int height();
|
||||
SDL_Surface *getSurface() { return surface; }
|
||||
|
||||
// Fill with a given pixel value
|
||||
void fill(int value);
|
||||
|
||||
// Set one pixel
|
||||
void pixel(int x, int y, int value);
|
||||
|
||||
const SpriteData *lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
// The SDL surface
|
||||
SDL_Surface* surface;
|
||||
|
||||
// Used for locking
|
||||
SpriteData data;
|
||||
|
||||
// If true, delete this surface when the canvas is destructed
|
||||
bool autoDel;
|
||||
};
|
||||
|
||||
class SDLDriver : public Driver
|
||||
{
|
||||
// The main display surface
|
||||
SDL_Sprite *display;
|
||||
|
||||
// The actual display surface. May or may not be the same
|
||||
// surface pointed to by 'display' above, depending on the
|
||||
// softDouble flag.
|
||||
SDL_Surface *realDisp;
|
||||
|
||||
// If true, we do software double buffering.
|
||||
bool softDouble;
|
||||
|
||||
public:
|
||||
SDLDriver();
|
||||
~SDLDriver();
|
||||
|
||||
/// Sets the video mode. Will create the window if it is not
|
||||
/// already set up. Note that for SDL, bpp=0 means use current
|
||||
/// bpp.
|
||||
void setVideoMode(int width, int height, int bpp=0, bool fullscreen=false);
|
||||
|
||||
/// Update the screen
|
||||
void update();
|
||||
|
||||
/// Set the window title, as well as the title of the window
|
||||
/// when "iconified"
|
||||
void setWindowTitle(const std::string &title,
|
||||
const std::string &icon);
|
||||
|
||||
// Include overloads from our Glorious parent
|
||||
using Driver::setWindowTitle;
|
||||
|
||||
/// Load sprite from an image file, using SDL_image.
|
||||
Sprite* loadImage(const std::string &file);
|
||||
|
||||
/// Load sprite from an SDL_RWops structure. autoFree determines
|
||||
/// whether the RWops struct should be closed/freed after use.
|
||||
Sprite* loadImage(SDL_RWops *src, bool autoFree=false);
|
||||
|
||||
/// Load a sprite from an image file stored in memory. Uses
|
||||
/// SDL_image.
|
||||
Sprite* loadImage(const void* data, size_t size);
|
||||
|
||||
/// Set gamma value
|
||||
void setGamma(float gamma) { setGamma(gamma,gamma,gamma); }
|
||||
|
||||
/// Set gamma individually for red, green, blue
|
||||
void setGamma(float red, float green, float blue);
|
||||
|
||||
/// Convert an existing SDL surface into a sprite
|
||||
Sprite* spriteFromSDL(SDL_Surface *surf, bool autoFree = true);
|
||||
|
||||
// Get width and height
|
||||
int width() { return display ? display->width() : 0; }
|
||||
int height() { return display ? display->height() : 0; }
|
||||
|
||||
/// Get the screen sprite
|
||||
Sprite *getScreen() { return display; }
|
||||
|
||||
/// Not really a graphic-related function, but very
|
||||
/// handly. Sleeps the given number of milliseconds using
|
||||
/// SDL_Delay().
|
||||
void sleep(int ms);
|
||||
|
||||
/// Get the number of ticks since SDL initialization, using
|
||||
/// SDL_GetTicks().
|
||||
unsigned int ticks();
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,311 +0,0 @@
|
||||
#include "sdl_gl_driver.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
using namespace Mangle::Rend2D;
|
||||
|
||||
void SDLGL_Sprite::draw(Sprite *s, // Must be SDLGL_Sprite
|
||||
int x, int y, // Destination position
|
||||
int sx, int sy, // Source position
|
||||
int w, int h // Amount to draw. -1 means remainder.
|
||||
)
|
||||
{
|
||||
// Get source surface
|
||||
SDLGL_Sprite *other = dynamic_cast<SDLGL_Sprite*>(s);
|
||||
assert(other != NULL);
|
||||
SDL_Surface *img = other->getSurface();
|
||||
|
||||
// Check coordinate validity
|
||||
assert(sx <= img->w && sy <= img->h);
|
||||
assert(x <= surface->w && y <= surface->h);
|
||||
assert(sx >= 0 && sy >= 0);
|
||||
|
||||
// Compute width and height if necessary
|
||||
if(w == -1) w = img->w - sx;
|
||||
if(h == -1) h = img->h - sy;
|
||||
|
||||
// Check them if they're valid
|
||||
assert(w >= 0 && w <= img->w);
|
||||
assert(h >= 0 && h <= img->h);
|
||||
|
||||
SDL_Rect dest;
|
||||
dest.x = x;
|
||||
dest.y = y;
|
||||
dest.w = w;
|
||||
dest.h = h;
|
||||
|
||||
SDL_Rect src;
|
||||
src.x = sx;
|
||||
src.y = sy;
|
||||
src.w = w;
|
||||
src.h = h;
|
||||
|
||||
// Do the Blitman
|
||||
SDL_BlitSurface(img, &src, surface, &dest);
|
||||
}
|
||||
|
||||
SDLGL_Sprite::SDLGL_Sprite(SDL_Surface *s, bool autoDelete)
|
||||
: surface(s), autoDel(autoDelete)
|
||||
{
|
||||
assert(surface != NULL);
|
||||
}
|
||||
|
||||
SDLGL_Sprite::~SDLGL_Sprite()
|
||||
{
|
||||
if(autoDel)
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
void SDLGL_Sprite::fill(int value)
|
||||
{
|
||||
SDL_FillRect(surface, NULL, value);
|
||||
}
|
||||
|
||||
int SDLGL_Sprite::width() { return surface->w; }
|
||||
int SDLGL_Sprite::height() { return surface->h; }
|
||||
|
||||
SDLGLDriver::SDLGLDriver() : display(NULL), realDisp(NULL)
|
||||
{
|
||||
if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1)
|
||||
throw std::runtime_error("Error initializing SDL video");
|
||||
}
|
||||
SDLGLDriver::~SDLGLDriver()
|
||||
{
|
||||
if(display) delete display;
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// Surface used for the screen. Since OpenGL surfaces must have sizes
|
||||
// that are powers of 2, we have to "fake" the returned display size
|
||||
// to match the screen, not the surface itself. If we don't use this,
|
||||
// the client program will get confused about the actual size of our
|
||||
// screen, thinking it is bigger than it is.
|
||||
struct FakeSizeSprite : SDLGL_Sprite
|
||||
{
|
||||
int fakeW, fakeH;
|
||||
|
||||
FakeSizeSprite(SDL_Surface *s, int fw, int fh)
|
||||
: SDLGL_Sprite(s), fakeW(fw), fakeH(fh)
|
||||
{}
|
||||
|
||||
int width() { return fakeW; }
|
||||
int height() { return fakeH; }
|
||||
};
|
||||
|
||||
static int makePow2(int num)
|
||||
{
|
||||
assert(num);
|
||||
if((num & (num-1)) != 0)
|
||||
{
|
||||
int cnt = 0;
|
||||
while(num)
|
||||
{
|
||||
num >>= 1;
|
||||
cnt++;
|
||||
}
|
||||
num = 1 << cnt;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
void SDLGLDriver::setVideoMode(int width, int height, int bpp, bool fullscreen)
|
||||
{
|
||||
unsigned int flags;
|
||||
|
||||
if(display) delete display;
|
||||
|
||||
flags = SDL_OPENGL;
|
||||
|
||||
if (fullscreen)
|
||||
flags |= SDL_FULLSCREEN;
|
||||
|
||||
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
||||
SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1 );
|
||||
|
||||
// Create the surface and check it
|
||||
screen = SDL_SetVideoMode(width, height, bpp, flags);
|
||||
if(screen == NULL)
|
||||
throw std::runtime_error("Failed setting SDL video mode");
|
||||
|
||||
// Expand width and height to be powers of 2
|
||||
int width2 = makePow2(width);
|
||||
int height2 = makePow2(height);
|
||||
|
||||
// Create a new SDL surface of this size
|
||||
const SDL_PixelFormat& fmt = *(screen->format);
|
||||
realDisp = SDL_CreateRGBSurface(SDL_SWSURFACE,width2,height2,
|
||||
fmt.BitsPerPixel,
|
||||
fmt.Rmask,fmt.Gmask,fmt.Bmask,fmt.Amask);
|
||||
|
||||
// Create a sprite directly representing the display surface. This
|
||||
// allows the user to blit to it directly.
|
||||
display = new FakeSizeSprite(realDisp, width, height);
|
||||
|
||||
// Set up the OpenGL format
|
||||
nOfColors = fmt.BytesPerPixel;
|
||||
|
||||
if(nOfColors == 4)
|
||||
{
|
||||
if (fmt.Rmask == 0x000000ff)
|
||||
texture_format = GL_RGBA;
|
||||
else
|
||||
texture_format = GL_BGRA;
|
||||
}
|
||||
else if(nOfColors == 3)
|
||||
{
|
||||
if (fmt.Rmask == 0x000000ff)
|
||||
texture_format = GL_RGB;
|
||||
else
|
||||
texture_format = GL_BGR;
|
||||
}
|
||||
else
|
||||
assert(0 && "unsupported screen format");
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Have OpenGL generate a texture object handle for us
|
||||
glGenTextures( 1, &texture );
|
||||
|
||||
// Bind the texture object
|
||||
glBindTexture( GL_TEXTURE_2D, texture );
|
||||
|
||||
// Set the texture's stretching properties
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
}
|
||||
|
||||
void SDLGLDriver::updateNoSwap()
|
||||
{
|
||||
if(!realDisp) return;
|
||||
|
||||
// Fist, set up the screen texture:
|
||||
|
||||
// Bind the texture object
|
||||
glBindTexture( GL_TEXTURE_2D, texture );
|
||||
|
||||
// Edit the texture object's image data
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, realDisp->w, realDisp->h, 0,
|
||||
texture_format, GL_UNSIGNED_BYTE, realDisp->pixels );
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
|
||||
// OpenGL barf. Set up the projection to match our screen
|
||||
int vPort[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vPort);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
|
||||
// Needed to move the screen into the right place
|
||||
int diff = screen->h - realDisp->h;
|
||||
|
||||
// Bottom-left vertex (corner)
|
||||
glTexCoord2i( 0, 1 );
|
||||
glVertex3f(0,diff,0);
|
||||
|
||||
// Bottom-right vertex (corner)
|
||||
glTexCoord2i( 1, 1 );
|
||||
glVertex3f( realDisp->w, diff, 0.f );
|
||||
|
||||
// Top-right vertex (corner)
|
||||
glTexCoord2i( 1, 0 );
|
||||
glVertex3f( realDisp->w, screen->h, 0.f );
|
||||
|
||||
// Top-left vertex (corner)
|
||||
glTexCoord2i( 0, 0 );
|
||||
glVertex3f( 0, screen->h, 0.f );
|
||||
glEnd();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void SDLGLDriver::swap()
|
||||
{
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
void SDLGLDriver::update()
|
||||
{
|
||||
updateNoSwap();
|
||||
swap();
|
||||
}
|
||||
|
||||
/// Set the window title, as well as the title of the window when
|
||||
/// "iconified"
|
||||
void SDLGLDriver::setWindowTitle(const std::string &title,
|
||||
const std::string &icon)
|
||||
{
|
||||
SDL_WM_SetCaption( title.c_str(), icon.c_str() );
|
||||
}
|
||||
|
||||
// Convert the given surface to display format.
|
||||
static SDL_Surface* convertImage(SDL_Surface* surf)
|
||||
{
|
||||
if(surf != NULL)
|
||||
{
|
||||
// Convert the image to the display buffer format, for faster
|
||||
// blitting
|
||||
SDL_Surface *surf2 = SDL_DisplayFormat(surf);
|
||||
SDL_FreeSurface(surf);
|
||||
surf = surf2;
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
|
||||
/// Load sprite from an image file, using SDL_image.
|
||||
Sprite* SDLGLDriver::loadImage(const std::string &file)
|
||||
{
|
||||
SDL_Surface *surf = IMG_Load(file.c_str());
|
||||
surf = convertImage(surf);
|
||||
if(surf == NULL)
|
||||
throw std::runtime_error("SDL failed to load image file '" + file + "'");
|
||||
return spriteFromSDL(surf);
|
||||
}
|
||||
|
||||
/// Load sprite from an SDL_RWops structure. autoFree determines
|
||||
/// whether the RWops struct should be closed/freed after use.
|
||||
Sprite* SDLGLDriver::loadImage(SDL_RWops *src, bool autoFree)
|
||||
{
|
||||
SDL_Surface *surf = IMG_Load_RW(src, autoFree);
|
||||
surf = convertImage(surf);
|
||||
if(surf == NULL)
|
||||
throw std::runtime_error("SDL failed to load image");
|
||||
return spriteFromSDL(surf);
|
||||
}
|
||||
|
||||
/// Load a sprite from an image file stored in memory. Uses
|
||||
/// SDL_image.
|
||||
Sprite* SDLGLDriver::loadImage(const void* data, size_t size)
|
||||
{
|
||||
SDL_RWops *rw = SDL_RWFromConstMem(data, size);
|
||||
return loadImage(rw, true);
|
||||
}
|
||||
|
||||
void SDLGLDriver::setGamma(float red, float green, float blue)
|
||||
{
|
||||
SDL_SetGamma(red,green,blue);
|
||||
}
|
||||
|
||||
/// Convert an existing SDL surface into a sprite
|
||||
Sprite* SDLGLDriver::spriteFromSDL(SDL_Surface *surf, bool autoFree)
|
||||
{
|
||||
assert(surf);
|
||||
return new SDLGL_Sprite(surf, autoFree);
|
||||
}
|
||||
|
||||
void SDLGLDriver::sleep(int ms) { SDL_Delay(ms); }
|
||||
unsigned int SDLGLDriver::ticks() { return SDL_GetTicks(); }
|
@ -1,132 +0,0 @@
|
||||
#ifndef MANGLE_DRAW2D_SDLGL_H
|
||||
#define MANGLE_DRAW2D_SDLGL_H
|
||||
|
||||
/** This driver is similar to SDLDriver, except that it uses SDL on
|
||||
top of OpenGL.
|
||||
|
||||
I've decided to make it a separate file instead of just adding
|
||||
optional OpenGL support to the original, so that pure SDL users
|
||||
don't have to add OpenGL as a dependency.
|
||||
*/
|
||||
|
||||
#include "../driver.hpp"
|
||||
|
||||
// Predeclarations keep the streets safe at night
|
||||
struct SDL_Surface;
|
||||
struct SDL_RWops;
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Rend2D
|
||||
{
|
||||
/// SDL-implementation of Sprite
|
||||
struct SDLGL_Sprite : Sprite
|
||||
{
|
||||
/** Draw a sprite in the given position. Can only draw other SDL
|
||||
sprites.
|
||||
*/
|
||||
void draw(Sprite *s, // Must be SDLGL_Sprite
|
||||
int x, int y, // Destination position
|
||||
int sx=0, int sy=0, // Source position
|
||||
int w=-1, int h=-1 // Amount to draw. -1 means remainder.
|
||||
);
|
||||
|
||||
SDLGL_Sprite(SDL_Surface *s, bool autoDelete=true);
|
||||
~SDLGL_Sprite();
|
||||
|
||||
// Information retrieval
|
||||
virtual int width();
|
||||
virtual int height();
|
||||
SDL_Surface *getSurface() { return surface; }
|
||||
|
||||
// Fill with a given pixel value
|
||||
void fill(int value);
|
||||
|
||||
private:
|
||||
// The SDL surface
|
||||
SDL_Surface* surface;
|
||||
|
||||
// If true, delete this surface when the canvas is destructed
|
||||
bool autoDel;
|
||||
};
|
||||
|
||||
class SDLGLDriver : public Driver
|
||||
{
|
||||
// The main display surface
|
||||
SDLGL_Sprite *display;
|
||||
|
||||
// The screen surface. This is completely unused.
|
||||
SDL_Surface *screen;
|
||||
|
||||
// The display surface and main GL texture. These are used when
|
||||
// drawing the entire screen as one surface, as a drop-in
|
||||
// replacement for SDLDriver.
|
||||
SDL_Surface *realDisp;
|
||||
unsigned int texture;
|
||||
int nOfColors, texture_format;
|
||||
|
||||
public:
|
||||
SDLGLDriver();
|
||||
~SDLGLDriver();
|
||||
|
||||
/// Sets the video mode. Will create the window if it is not
|
||||
/// already set up. Note that for SDL, bpp=0 means use current
|
||||
/// bpp.
|
||||
void setVideoMode(int width, int height, int bpp=0, bool fullscreen=false);
|
||||
|
||||
/// Update the screen
|
||||
void update();
|
||||
|
||||
/// Calls SDL_GL_SwapBuffers
|
||||
void swap();
|
||||
|
||||
/// Draw surface to screen but do not call SDL_GL_SwapBuffers()
|
||||
void updateNoSwap();
|
||||
|
||||
/// Set the window title, as well as the title of the window
|
||||
/// when "iconified"
|
||||
void setWindowTitle(const std::string &title,
|
||||
const std::string &icon);
|
||||
|
||||
// Include overloads from our Glorious parent
|
||||
using Driver::setWindowTitle;
|
||||
|
||||
/// Load sprite from an image file, using SDL_image.
|
||||
Sprite* loadImage(const std::string &file);
|
||||
|
||||
/// Load sprite from an SDL_RWops structure. autoFree determines
|
||||
/// whether the RWops struct should be closed/freed after use.
|
||||
Sprite* loadImage(SDL_RWops *src, bool autoFree=false);
|
||||
|
||||
/// Load a sprite from an image file stored in memory. Uses
|
||||
/// SDL_image.
|
||||
Sprite* loadImage(const void* data, size_t size);
|
||||
|
||||
/// Set gamma value
|
||||
void setGamma(float gamma) { setGamma(gamma,gamma,gamma); }
|
||||
|
||||
/// Set gamma individually for red, green, blue
|
||||
void setGamma(float red, float green, float blue);
|
||||
|
||||
/// Convert an existing SDL surface into a sprite
|
||||
Sprite* spriteFromSDL(SDL_Surface *surf, bool autoFree = true);
|
||||
|
||||
// Get width and height
|
||||
int width() { return display ? display->width() : 0; }
|
||||
int height() { return display ? display->height() : 0; }
|
||||
|
||||
/// Get the screen sprite
|
||||
Sprite *getScreen() { return display; }
|
||||
|
||||
/// Not really a graphic-related function, but very
|
||||
/// handly. Sleeps the given number of milliseconds using
|
||||
/// SDL_Delay().
|
||||
void sleep(int ms);
|
||||
|
||||
/// Get the number of ticks since SDL initialization, using
|
||||
/// SDL_GetTicks().
|
||||
unsigned int ticks();
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,57 +0,0 @@
|
||||
#ifndef MANGLE_REND2D_SPRITE_H
|
||||
#define MANGLE_REND2D_SPRITE_H
|
||||
|
||||
namespace Mangle
|
||||
{
|
||||
namespace Rend2D
|
||||
{
|
||||
/**
|
||||
A pointer to sprite data for direct drawing. Only to be used
|
||||
while the corresponding sprite is locked.
|
||||
*/
|
||||
struct SpriteData
|
||||
{
|
||||
void *pixels; // Pixel data
|
||||
int w, h; // Width and height
|
||||
int pitch, bypp; // Pitch (bytes) and bytes per pixel
|
||||
};
|
||||
|
||||
/**
|
||||
A Sprite is either a bitmap to be drawn or an output of area
|
||||
for blitting other bitmaps, or both. They are created by the
|
||||
Driver.
|
||||
*/
|
||||
struct Sprite
|
||||
{
|
||||
/// Draw a sprite in the given position
|
||||
virtual void draw(Sprite *s, // The sprite to draw
|
||||
int x, int y, // Destination position
|
||||
int sx=0, int sy=0, // Source position
|
||||
int w=-1, int h=-1 // Amount to draw. -1 means remainder.
|
||||
) = 0;
|
||||
|
||||
virtual ~Sprite() {}
|
||||
|
||||
// Information retrieval
|
||||
virtual int width() = 0;
|
||||
virtual int height() = 0;
|
||||
|
||||
/// Fill the sprite with the given pixel value. The pixel format
|
||||
/// depends on the format of the sprite.
|
||||
virtual void fill(int value) = 0;
|
||||
|
||||
/// Set one pixel value. The pixel format depends on the sprite
|
||||
/// format. This is not expected to be fast, and in some
|
||||
/// implementations may not work at all.
|
||||
virtual void pixel(int x, int y, int value) {}
|
||||
|
||||
/// Lock sprite for direct drawing, and return a struct
|
||||
/// containing the necessary pointer. When finished, unlock the
|
||||
/// sprite with unlock(). May return NULL, if so then direct
|
||||
/// drawing is not possible.
|
||||
virtual const SpriteData *lock() { return NULL; }
|
||||
virtual void unlock() {}
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1 +0,0 @@
|
||||
*_test
|
@ -1,15 +0,0 @@
|
||||
GCC=g++ -Wall -Werror
|
||||
|
||||
all: sdl_test sdl_move_test sdlgl_move_test
|
||||
|
||||
sdl_test: sdl_test.cpp
|
||||
$(GCC) $< ../servers/sdl_driver.cpp -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image
|
||||
|
||||
sdl_move_test: sdl_move_test.cpp ../servers/sdl_driver.cpp
|
||||
$(GCC) $^ -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image
|
||||
|
||||
sdlgl_move_test: sdlgl_move_test.cpp ../servers/sdl_gl_driver.cpp
|
||||
$(GCC) $^ -o $@ -I/usr/include/SDL/ -lSDL -lSDL_image -lGL
|
||||
|
||||
clean:
|
||||
rm *_test
|
@ -1,11 +0,0 @@
|
||||
Loading SDL driver.
|
||||
Creating window.
|
||||
Current mode: 640x480
|
||||
Setting fancy title, cause we like fancy titles.
|
||||
Loading tile1-blue.png from file.
|
||||
Loading tile1-yellow.png from memory.
|
||||
Going bananas.
|
||||
Taking a breather.
|
||||
WOW DID YOU SEE THAT!?
|
||||
Mucking about with the gamma settings
|
||||
Done.
|
@ -1,30 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "../servers/sdl_driver.hpp"
|
||||
|
||||
using namespace Mangle::Rend2D;
|
||||
|
||||
int main()
|
||||
{
|
||||
SDLDriver sdl;
|
||||
|
||||
sdl.setVideoMode(640,480,0,false);
|
||||
sdl.setWindowTitle("Testing 123");
|
||||
Sprite *screen = sdl.getScreen();
|
||||
const char* imgName = "tile1-blue.png";
|
||||
Sprite *image = sdl.loadImage(imgName);
|
||||
|
||||
for(int frames=0; frames<170; frames++)
|
||||
{
|
||||
screen->fill(0);
|
||||
for(int j=0; j<10; j++)
|
||||
for(int i=0; i<25; i++)
|
||||
screen->draw(image, 2*frames+30*j, 20*i);
|
||||
sdl.update();
|
||||
sdl.sleep(10);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "../servers/sdl_driver.hpp"
|
||||
|
||||
using namespace Mangle::Rend2D;
|
||||
|
||||
int main()
|
||||
{
|
||||
cout << "Loading SDL driver.\n";
|
||||
SDLDriver sdl;
|
||||
|
||||
cout << "Creating window.\n";
|
||||
sdl.setVideoMode(640,480);
|
||||
cout << "Current mode: " << sdl.width() << "x" << sdl.height() << endl;
|
||||
|
||||
cout << "Setting fancy title, cause we like fancy titles.\n";
|
||||
sdl.setWindowTitle("Chief executive window");
|
||||
|
||||
// Display surface
|
||||
Sprite *screen = sdl.getScreen();
|
||||
|
||||
const char* imgName = "tile1-blue.png";
|
||||
cout << "Loading " << imgName << " from file.\n";
|
||||
Sprite *image = sdl.loadImage(imgName);
|
||||
|
||||
const char* imgName2 = "tile1-yellow.png";
|
||||
cout << "Loading " << imgName2 << " from memory.\n";
|
||||
Sprite *image2;
|
||||
{
|
||||
// This is hard-coded for file sizes below 500 bytes, so obviously
|
||||
// you shouldn't mess with the image files.
|
||||
ifstream file(imgName2, ios::binary);
|
||||
char buf[500];
|
||||
file.read(buf, 500);
|
||||
int size = file.gcount();
|
||||
image2 = sdl.loadImage(buf, size);
|
||||
}
|
||||
|
||||
cout << "Going bananas.\n";
|
||||
for(int i=1; i<20; i++)
|
||||
screen->draw(image, 30*i, 20*i);
|
||||
|
||||
cout << "Taking a breather.\n";
|
||||
sdl.update();
|
||||
for(int i=1; i<20; i++)
|
||||
screen->draw(image2, 30*(20-i), 20*i);
|
||||
sdl.sleep(800);
|
||||
sdl.update();
|
||||
cout << "WOW DID YOU SEE THAT!?\n";
|
||||
sdl.sleep(800);
|
||||
|
||||
cout << "Mucking about with the gamma settings\n";
|
||||
sdl.setGamma(2.0, 0.1, 0.8);
|
||||
sdl.sleep(100);
|
||||
sdl.setGamma(0.6, 2.1, 2.1);
|
||||
sdl.sleep(100);
|
||||
sdl.setGamma(1.6);
|
||||
sdl.sleep(100);
|
||||
|
||||
cout << "Done.\n";
|
||||
return 0;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "../servers/sdl_gl_driver.hpp"
|
||||
|
||||
using namespace Mangle::Rend2D;
|
||||
|
||||
int main()
|
||||
{
|
||||
SDLGLDriver sdl;
|
||||
|
||||
sdl.setVideoMode(640,480,0,false);
|
||||
sdl.setWindowTitle("Testing 123");
|
||||
Sprite *screen = sdl.getScreen();
|
||||
const char* imgName = "tile1-blue.png";
|
||||
Sprite *image = sdl.loadImage(imgName);
|
||||
|
||||
for(int frames=0; frames<170; frames++)
|
||||
{
|
||||
screen->fill(0);
|
||||
for(int j=0; j<10; j++)
|
||||
for(int i=0; i<25; i++)
|
||||
screen->draw(image, 2*frames+30*j, 20*i);
|
||||
sdl.update();
|
||||
sdl.sleep(5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
make || exit
|
||||
|
||||
mkdir -p output
|
||||
|
||||
PROGS=*_test
|
||||
|
||||
for a in $PROGS; do
|
||||
if [ -f "output/$a.out" ]; then
|
||||
echo "Running $a:"
|
||||
./$a | diff output/$a.out -
|
||||
else
|
||||
echo "Creating $a.out"
|
||||
./$a > "output/$a.out"
|
||||
git add "output/$a.out"
|
||||
fi
|
||||
done
|
Binary file not shown.
Before Width: | Height: | Size: 273 B |
Binary file not shown.
Before Width: | Height: | Size: 257 B |
@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
function run()
|
||||
{
|
||||
echo "TESTING $1"
|
||||
cd "$1/tests/"
|
||||
./test.sh
|
||||
cd ../../
|
||||
}
|
||||
|
||||
run stream
|
||||
run vfs
|
||||
run sound
|
||||
run input
|
||||
run rend2d
|
||||
run .
|
@ -1 +0,0 @@
|
||||
*_test
|
@ -1,14 +0,0 @@
|
||||
GCC=g++ -I../
|
||||
|
||||
all: ogrevfs_audiere_openal_test
|
||||
|
||||
I_OGRE=$(shell pkg-config --cflags OGRE)
|
||||
L_OGRE=$(shell pkg-config --libs OGRE)
|
||||
L_OPENAL=$(shell pkg-config --libs openal)
|
||||
L_AUDIERE=-laudiere
|
||||
|
||||
ogrevfs_audiere_openal_test: ogrevfs_audiere_openal_test.cpp ../vfs/servers/ogre_vfs.cpp ../sound/sources/audiere_source.cpp ../sound/outputs/openal_out.cpp ../stream/clients/audiere_file.cpp
|
||||
$(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) $(L_OPENAL) $(L_AUDIERE)
|
||||
|
||||
clean:
|
||||
rm *_test
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
This example combines:
|
||||
|
||||
- the OGRE VFS system (to read from zip)
|
||||
- Audiere (for decoding sound data)
|
||||
- OpenAL (for sound playback)
|
||||
|
||||
*/
|
||||
|
||||
#include "sound/filters/openal_audiere.hpp"
|
||||
#include "vfs/servers/ogre_vfs.hpp"
|
||||
#include <Ogre.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace Mangle;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Disable Ogre logging
|
||||
new LogManager;
|
||||
Log *log = LogManager::getSingleton().createLog("");
|
||||
log->setDebugOutputEnabled(false);
|
||||
|
||||
// Set up Root
|
||||
Root *root = new Root("","","");
|
||||
|
||||
// Add zip file with a sound in it
|
||||
root->addResourceLocation("sound.zip", "Zip", "General");
|
||||
|
||||
// Ogre file system
|
||||
VFS::OgreVFS vfs;
|
||||
|
||||
// The main sound system
|
||||
Sound::OpenAL_Audiere_Factory mg;
|
||||
Sound::SoundPtr snd = mg.load(vfs.open("owl.ogg"));
|
||||
|
||||
cout << "Playing 'owl.ogg' from 'sound.zip'\n";
|
||||
snd->play();
|
||||
|
||||
while(snd->isPlaying())
|
||||
{
|
||||
usleep(10000);
|
||||
if(mg.needsUpdate) mg.update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1 +0,0 @@
|
||||
Playing 'owl.ogg' from 'sound.zip'
|
Binary file not shown.
@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
make || exit
|
||||
|
||||
mkdir -p output
|
||||
|
||||
PROGS=*_test
|
||||
|
||||
for a in $PROGS; do
|
||||
if [ -f "output/$a.out" ]; then
|
||||
echo "Running $a:"
|
||||
./$a | diff output/$a.out -
|
||||
else
|
||||
echo "Creating $a.out"
|
||||
./$a > "output/$a.out"
|
||||
git add "output/$a.out"
|
||||
fi
|
||||
done
|
@ -1,3 +0,0 @@
|
||||
// This file should include whatever it needs to define the boost/tr1
|
||||
// shared_ptr<> and weak_ptr<> templates.
|
||||
#include <boost/smart_ptr.hpp>
|
@ -1,77 +0,0 @@
|
||||
#include <MyGUI.h>
|
||||
#include <OIS/OIS.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "events.hpp"
|
||||
|
||||
using namespace OIS;
|
||||
using namespace OEngine::GUI;
|
||||
|
||||
EventInjector::EventInjector(MyGUI::Gui *g)
|
||||
: gui(g), enabled(true)
|
||||
, mMouseX(0)
|
||||
, mMouseY(0)
|
||||
{
|
||||
assert(gui);
|
||||
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
mMouseX = viewSize.width/2;
|
||||
mMouseY = viewSize.height/2;
|
||||
}
|
||||
|
||||
void EventInjector::event(Type type, int index, const void *p)
|
||||
{
|
||||
if(!enabled) return;
|
||||
|
||||
if(type & EV_Keyboard)
|
||||
{
|
||||
KeyEvent *key = (KeyEvent*)p;
|
||||
MyGUI::KeyCode code = MyGUI::KeyCode::Enum(key->key);
|
||||
if(type == EV_KeyDown)
|
||||
{
|
||||
/*
|
||||
This is just a first approximation. Apparently, OIS is
|
||||
unable to provide reliable unicode characters on all
|
||||
platforms. At least that's what I surmise from the amount
|
||||
of workaround that the MyGUI folks have put in place for
|
||||
this. See Common/Input/OIS/InputManager.cpp in the MyGUI
|
||||
sources for details.
|
||||
|
||||
If the work they have done there is indeed necessary (I
|
||||
haven't tested that it is, although I have had dubious
|
||||
experinces with OIS events in the past), then we should
|
||||
probably adapt all that code here. Or even better,
|
||||
directly into the OIS input manager in Mangle.
|
||||
|
||||
Note that all this only affects the 'text' field, and
|
||||
should thus only affect typed text in input boxes (which
|
||||
is still pretty significant.)
|
||||
*/
|
||||
MyGUI::Char text = (MyGUI::Char)key->text;
|
||||
MyGUI::InputManager::getInstance().injectKeyPress(code,text);
|
||||
}
|
||||
else
|
||||
{
|
||||
MyGUI::InputManager::getInstance().injectKeyRelease(code);
|
||||
}
|
||||
}
|
||||
else if(type & EV_Mouse)
|
||||
{
|
||||
MouseEvent *mouse = (MouseEvent*)p;
|
||||
MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index);
|
||||
|
||||
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
||||
// Update mouse position
|
||||
mMouseX += mouse->state.X.rel;
|
||||
mMouseY += mouse->state.Y.rel;
|
||||
mMouseX = std::max(0, std::min(mMouseX, viewSize.width));
|
||||
mMouseY = std::max(0, std::min(mMouseY, viewSize.height));
|
||||
|
||||
if(type == EV_MouseDown)
|
||||
MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, id);
|
||||
else if(type == EV_MouseUp)
|
||||
MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, id);
|
||||
else
|
||||
MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mouse->state.Z.abs);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#ifndef OENGINE_MYGUI_EVENTS_H
|
||||
#define OENGINE_MYGUI_EVENTS_H
|
||||
|
||||
#include <mangle/input/event.hpp>
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Gui;
|
||||
}
|
||||
|
||||
namespace OEngine {
|
||||
namespace GUI
|
||||
{
|
||||
/** Event handler that injects OIS events into MyGUI
|
||||
*/
|
||||
class EventInjector : public Mangle::Input::Event
|
||||
{
|
||||
MyGUI::Gui *gui;
|
||||
|
||||
int mMouseX;
|
||||
int mMouseY;
|
||||
|
||||
public:
|
||||
bool enabled;
|
||||
|
||||
EventInjector(MyGUI::Gui *g);
|
||||
void event(Type type, int index, const void *p);
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<EventInjector> EventInjectorPtr;
|
||||
}}
|
||||
#endif
|
@ -1,57 +0,0 @@
|
||||
#include "mouselook.hpp"
|
||||
|
||||
#include <OIS/OIS.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
using namespace OIS;
|
||||
using namespace Ogre;
|
||||
using namespace OEngine::Render;
|
||||
|
||||
void MouseLookEvent::event(Type type, int index, const void *p)
|
||||
{
|
||||
if(type != EV_MouseMove || camera == NULL) return;
|
||||
|
||||
MouseEvent *arg = (MouseEvent*)(p);
|
||||
|
||||
float x = arg->state.X.rel * sensX;
|
||||
float y = arg->state.Y.rel * sensY;
|
||||
|
||||
camera->getParentSceneNode()->getParentSceneNode()->yaw(Degree(-x));
|
||||
camera->getParentSceneNode()->pitch(Degree(-y));
|
||||
if(flipProt)
|
||||
{
|
||||
// The camera before pitching
|
||||
/*Quaternion nopitch = camera->getParentSceneNode()->getOrientation();
|
||||
|
||||
camera->getParentSceneNode()->pitch(Degree(-y));
|
||||
|
||||
// Apply some failsafe measures against the camera flipping
|
||||
// upside down. Is the camera close to pointing straight up or
|
||||
// down?
|
||||
if(Ogre::Vector3(camera->getParentSceneNode()->getOrientation()*Ogre::Vector3::UNIT_Y)[1] <= 0.1)
|
||||
// If so, undo the last pitch
|
||||
camera->getParentSceneNode()->setOrientation(nopitch);*/
|
||||
//camera->getU
|
||||
|
||||
// Angle of rotation around the X-axis.
|
||||
float pitchAngle = (2 * Ogre::Degree(Ogre::Math::ACos(camera->getParentSceneNode()->getOrientation().w)).valueDegrees());
|
||||
|
||||
// Just to determine the sign of the angle we pick up above, the
|
||||
// value itself does not interest us.
|
||||
float pitchAngleSign = camera->getParentSceneNode()->getOrientation().x;
|
||||
|
||||
// Limit the pitch between -90 degress and +90 degrees, Quake3-style.
|
||||
if (pitchAngle > 90.0f)
|
||||
{
|
||||
if (pitchAngleSign > 0)
|
||||
// Set orientation to 90 degrees on X-axis.
|
||||
camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f),
|
||||
Ogre::Math::Sqrt(0.5f), 0, 0));
|
||||
else if (pitchAngleSign < 0)
|
||||
// Sets orientation to -90 degrees on X-axis.
|
||||
camera->getParentSceneNode()->setOrientation(Ogre::Quaternion(Ogre::Math::Sqrt(0.5f),
|
||||
-Ogre::Math::Sqrt(0.5f), 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
#ifndef OENGINE_OGRE_MOUSELOOK_H
|
||||
#define OENGINE_OGRE_MOUSELOOK_H
|
||||
|
||||
/*
|
||||
A mouse-look class for Ogre. Accepts input events from Mangle::Input
|
||||
and translates them.
|
||||
|
||||
You can adjust the mouse sensibility and switch to a different
|
||||
camera. The mouselook class also has an optional wrap protection
|
||||
that keeps the camera from flipping upside down.
|
||||
|
||||
You can disable the mouse looker at any time by calling
|
||||
setCamera(NULL), and reenable it by setting the camera back.
|
||||
|
||||
NOTE: The current implementation will ONLY work for native OIS
|
||||
events.
|
||||
*/
|
||||
|
||||
#include <mangle/input/event.hpp>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Camera;
|
||||
}
|
||||
|
||||
namespace OEngine {
|
||||
namespace Render
|
||||
{
|
||||
class MouseLookEvent : public Mangle::Input::Event
|
||||
{
|
||||
Ogre::Camera* camera;
|
||||
float sensX, sensY; // Mouse sensibility
|
||||
bool flipProt; // Flip protection
|
||||
|
||||
public:
|
||||
MouseLookEvent(Ogre::Camera *cam=NULL,
|
||||
float sX=0.2, float sY=0.2,
|
||||
bool prot=true)
|
||||
: camera(cam)
|
||||
, sensX(sX)
|
||||
, sensY(sY)
|
||||
, flipProt(prot)
|
||||
{}
|
||||
|
||||
void setCamera(Ogre::Camera *cam)
|
||||
{ camera = cam; }
|
||||
void setSens(float sX, float sY)
|
||||
{ sensX = sX; sensY = sY; }
|
||||
void setProt(bool p) { flipProt = p; }
|
||||
|
||||
void event(Type type, int index, const void *p);
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<MouseLookEvent> MouseLookEventPtr;
|
||||
}}
|
||||
#endif
|
Loading…
Reference in New Issue