Non platform specific:
- normalize axes events - handle relative and absolute axes separately in own classes - ignore tolerance for relative axes, they can fire the same event multiple times which must not be ignored.
This commit is contained in:
parent
4023bdaf26
commit
26859ad4b9
4 changed files with 103 additions and 8 deletions
|
@ -74,10 +74,10 @@ FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_p
|
||||||
return new FGButtonEvent( device, node );
|
return new FGButtonEvent( device, node );
|
||||||
|
|
||||||
if( StartsWith( name, "rel-" ) )
|
if( StartsWith( name, "rel-" ) )
|
||||||
return new FGAxisEvent( device, node );
|
return new FGRelAxisEvent( device, node );
|
||||||
|
|
||||||
if( StartsWith( name, "abs-" ) )
|
if( StartsWith( name, "abs-" ) )
|
||||||
return new FGAxisEvent( device, node );
|
return new FGAbsAxisEvent( device, node );
|
||||||
|
|
||||||
return new FGInputEvent( device, node );
|
return new FGInputEvent( device, node );
|
||||||
}
|
}
|
||||||
|
@ -121,18 +121,25 @@ void FGInputEvent::fire( FGEventData & eventData )
|
||||||
if( lastDt >= intervalSec ) {
|
if( lastDt >= intervalSec ) {
|
||||||
|
|
||||||
for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
|
for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
|
||||||
(*it)->fire( eventData.value, 1.0 );
|
fire( *it, eventData );
|
||||||
|
|
||||||
lastDt -= intervalSec;
|
lastDt -= intervalSec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGInputEvent::fire( SGBinding * binding, FGEventData & eventData )
|
||||||
|
{
|
||||||
|
binding->fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
|
FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
|
||||||
FGInputEvent( device, node )
|
FGInputEvent( device, node )
|
||||||
{
|
{
|
||||||
tolerance = node->getDoubleValue("tolerance", 0.002);
|
tolerance = node->getDoubleValue("tolerance", 0.002);
|
||||||
minRange = node->getDoubleValue("min-range", -1024.0);
|
minRange = node->getDoubleValue("min-range", 0.0 );
|
||||||
maxRange = node->getDoubleValue("max-range", 1024.0);
|
maxRange = node->getDoubleValue("max-range", 0.0 );
|
||||||
center = node->getDoubleValue("center", 0.0);
|
center = node->getDoubleValue("center", 0.0);
|
||||||
deadband = node->getDoubleValue("dead-band", 0.0);
|
deadband = node->getDoubleValue("dead-band", 0.0);
|
||||||
lowThreshold = node->getDoubleValue("low-threshold", -0.9);
|
lowThreshold = node->getDoubleValue("low-threshold", -0.9);
|
||||||
|
@ -145,7 +152,36 @@ void FGAxisEvent::fire( FGEventData & eventData )
|
||||||
if (fabs( eventData.value - lastValue) < tolerance)
|
if (fabs( eventData.value - lastValue) < tolerance)
|
||||||
return;
|
return;
|
||||||
lastValue = eventData.value;
|
lastValue = eventData.value;
|
||||||
FGInputEvent::fire( eventData );
|
|
||||||
|
// We need a copy of the FGEventData struct to set the new value and to avoid side effects
|
||||||
|
FGEventData ed = eventData;
|
||||||
|
|
||||||
|
if( fabs(ed.value) < deadband )
|
||||||
|
ed.value = 0.0;
|
||||||
|
|
||||||
|
if( minRange != maxRange )
|
||||||
|
ed.value = 2.0*(eventData.value-minRange)/(maxRange-minRange)-1.0;
|
||||||
|
|
||||||
|
FGInputEvent::fire( ed );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGAbsAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
|
||||||
|
{
|
||||||
|
// sets the "setting" node
|
||||||
|
binding->fire( eventData.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
FGRelAxisEvent::FGRelAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
|
||||||
|
FGAxisEvent( device, node )
|
||||||
|
{
|
||||||
|
// relative axes can't use tolerance
|
||||||
|
tolerance = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGRelAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
|
||||||
|
{
|
||||||
|
// sets the "offset" node
|
||||||
|
binding->fire( eventData.value, 1.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
|
FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
|
||||||
|
|
|
@ -83,6 +83,7 @@ typedef vector<FGEventSetting_ptr> setting_list_t;
|
||||||
class FGInputDevice;
|
class FGInputDevice;
|
||||||
class FGInputEvent : public SGReferenced,FGCommonInput {
|
class FGInputEvent : public SGReferenced,FGCommonInput {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor for the class. The arg node shall point
|
* Constructor for the class. The arg node shall point
|
||||||
* to the property corresponding to the <event> node
|
* to the property corresponding to the <event> node
|
||||||
|
@ -110,6 +111,7 @@ public:
|
||||||
static FGInputEvent * NewObject( FGInputDevice * device, SGPropertyNode_ptr node );
|
static FGInputEvent * NewObject( FGInputDevice * device, SGPropertyNode_ptr node );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void fire( SGBinding * binding, FGEventData & eventData );
|
||||||
/* A more or less meaningfull description of the event */
|
/* A more or less meaningfull description of the event */
|
||||||
string desc;
|
string desc;
|
||||||
|
|
||||||
|
@ -143,6 +145,9 @@ protected:
|
||||||
class FGAxisEvent : public FGInputEvent {
|
class FGAxisEvent : public FGInputEvent {
|
||||||
public:
|
public:
|
||||||
FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node );
|
FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node );
|
||||||
|
void SetMaxRange( double value ) { maxRange = value; }
|
||||||
|
void SetMinRange( double value ) { minRange = value; }
|
||||||
|
void SetRange( double min, double max ) { minRange = min; maxRange = max; }
|
||||||
protected:
|
protected:
|
||||||
virtual void fire( FGEventData & eventData );
|
virtual void fire( FGEventData & eventData );
|
||||||
double tolerance;
|
double tolerance;
|
||||||
|
@ -155,6 +160,20 @@ protected:
|
||||||
double lastValue;
|
double lastValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FGRelAxisEvent : public FGAxisEvent {
|
||||||
|
public:
|
||||||
|
FGRelAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node );
|
||||||
|
protected:
|
||||||
|
virtual void fire( SGBinding * binding, FGEventData & eventData );
|
||||||
|
};
|
||||||
|
|
||||||
|
class FGAbsAxisEvent : public FGAxisEvent {
|
||||||
|
public:
|
||||||
|
FGAbsAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) : FGAxisEvent( device, node ) {}
|
||||||
|
protected:
|
||||||
|
virtual void fire( SGBinding * binding, FGEventData & eventData );
|
||||||
|
};
|
||||||
|
|
||||||
typedef class SGSharedPtr<FGInputEvent> FGInputEvent_ptr;
|
typedef class SGSharedPtr<FGInputEvent> FGInputEvent_ptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -273,6 +273,11 @@ FGLinuxInputDevice::FGLinuxInputDevice() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool bitSet( unsigned char * buf, unsigned char bit )
|
||||||
|
{
|
||||||
|
return (buf[bit/sizeof(bit)/8] >> (bit%(sizeof(bit)*8))) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
void FGLinuxInputDevice::Open()
|
void FGLinuxInputDevice::Open()
|
||||||
{
|
{
|
||||||
if( fd != -1 ) return;
|
if( fd != -1 ) return;
|
||||||
|
@ -280,9 +285,38 @@ void FGLinuxInputDevice::Open()
|
||||||
throw exception();
|
throw exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) != 0 ) {
|
if( GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) == -1 ) {
|
||||||
SG_LOG( SG_INPUT, SG_WARN, "Can't grab " << devname << " for exclusive access" );
|
SG_LOG( SG_INPUT, SG_WARN, "Can't grab " << devname << " for exclusive access" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char buf[ABS_CNT/sizeof(unsigned char)/8];
|
||||||
|
// get axes maximums
|
||||||
|
if( ioctl( fd, EVIOCGBIT(EV_ABS,ABS_MAX), buf ) == -1 ) {
|
||||||
|
SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes for " << devname );
|
||||||
|
} else {
|
||||||
|
for( unsigned i = 0; i < ABS_MAX; i++ ) {
|
||||||
|
if( bitSet( buf, i ) ) {
|
||||||
|
struct input_absinfo ai;
|
||||||
|
if( ioctl(fd, EVIOCGABS(i), &ai) == -1 ) {
|
||||||
|
SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes maximums for " << devname );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
absinfo[i] = ai;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double FGLinuxInputDevice::Normalize( struct input_event & event )
|
||||||
|
{
|
||||||
|
if( absinfo.count(event.code) > 0 ) {
|
||||||
|
const struct input_absinfo & ai = absinfo[(unsigned int)event.code];
|
||||||
|
if( ai.maximum == ai.minimum )
|
||||||
|
return 0.0;
|
||||||
|
return ((double)event.value-(double)ai.minimum)/((double)ai.maximum-(double)ai.minimum);
|
||||||
|
} else {
|
||||||
|
return (double)event.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLinuxInputDevice::Close()
|
void FGLinuxInputDevice::Close()
|
||||||
|
@ -437,7 +471,6 @@ void FGLinuxEventInput::AddHalDevice( const char * udi )
|
||||||
void FGLinuxEventInput::update( double dt )
|
void FGLinuxEventInput::update( double dt )
|
||||||
{
|
{
|
||||||
FGEventInput::update( dt );
|
FGEventInput::update( dt );
|
||||||
|
|
||||||
// index the input devices by the associated fd and prepare
|
// index the input devices by the associated fd and prepare
|
||||||
// the pollfd array by filling in the file descriptor
|
// the pollfd array by filling in the file descriptor
|
||||||
struct pollfd fds[input_devices.size()];
|
struct pollfd fds[input_devices.size()];
|
||||||
|
@ -468,6 +501,9 @@ void FGLinuxEventInput::update( double dt )
|
||||||
|
|
||||||
FGLinuxEventData eventData( event, dt, modifiers );
|
FGLinuxEventData eventData( event, dt, modifiers );
|
||||||
|
|
||||||
|
if( event.type == EV_ABS )
|
||||||
|
eventData.value = devicesByFd[fds[i].fd]->Normalize( event );
|
||||||
|
|
||||||
// let the FGInputDevice handle the data
|
// let the FGInputDevice handle the data
|
||||||
devicesByFd[fds[i].fd]->HandleEvent( eventData );
|
devicesByFd[fds[i].fd]->HandleEvent( eventData );
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,9 +56,12 @@ public:
|
||||||
|
|
||||||
int GetFd() { return fd; }
|
int GetFd() { return fd; }
|
||||||
|
|
||||||
|
double Normalize( struct input_event & event );
|
||||||
private:
|
private:
|
||||||
string devname;
|
string devname;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
map<unsigned int,input_absinfo> absinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGLinuxEventInput : public FGEventInput {
|
class FGLinuxEventInput : public FGEventInput {
|
||||||
|
@ -71,6 +74,7 @@ public:
|
||||||
void AddHalDevice( const char * udi );
|
void AddHalDevice( const char * udi );
|
||||||
protected:
|
protected:
|
||||||
LibHalContext *halcontext;
|
LibHalContext *halcontext;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue