]> git.mxchange.org Git - flightgear.git/commitdiff
Non platform specific:
authortorsten <torsten>
Thu, 1 Oct 2009 11:49:10 +0000 (11:49 +0000)
committerTim Moore <timoore@redhat.com>
Sun, 4 Oct 2009 00:02:47 +0000 (02:02 +0200)
- 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.

src/Input/FGEventInput.cxx
src/Input/FGEventInput.hxx
src/Input/FGLinuxEventInput.cxx
src/Input/FGLinuxEventInput.hxx

index 6ac1dd4af642b67c80877defd75664de973d45ca..928c20c242a58ddee1ea5e97eafef1f0f89580ff 100644 (file)
@@ -74,10 +74,10 @@ FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_p
     return new FGButtonEvent( device, node );
 
   if( StartsWith( name, "rel-" ) )
-    return new FGAxisEvent( device, node );
+    return new FGRelAxisEvent( device, node );
 
   if( StartsWith( name, "abs-" ) )
-    return new FGAxisEvent( device, node );
+    return new FGAbsAxisEvent( device, node );
 
   return new FGInputEvent( device, node );
 }
@@ -121,18 +121,25 @@ void FGInputEvent::fire( FGEventData & eventData )
   if( lastDt >= intervalSec ) {
 
     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;
   }
 }
 
+void FGInputEvent::fire( SGBinding * binding, FGEventData & eventData )
+{
+  binding->fire();
+}
+
+
+
 FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
   FGInputEvent( device, node )
 {
   tolerance = node->getDoubleValue("tolerance", 0.002);
-  minRange = node->getDoubleValue("min-range", -1024.0);
-  maxRange = node->getDoubleValue("max-range", 1024.0);
+  minRange = node->getDoubleValue("min-range", 0.0 );
+  maxRange = node->getDoubleValue("max-range", 0.0 );
   center = node->getDoubleValue("center", 0.0);
   deadband = node->getDoubleValue("dead-band", 0.0);
   lowThreshold = node->getDoubleValue("low-threshold", -0.9);
@@ -145,7 +152,36 @@ void FGAxisEvent::fire( FGEventData & eventData )
   if (fabs( eventData.value - lastValue) < tolerance)
     return;
   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 ) :
index 973821bd0584452c7bb10a8ecfc3ed3edc150aa5..7188c83813f112d844e0d2afae40a27c09465d34 100644 (file)
@@ -83,6 +83,7 @@ typedef vector<FGEventSetting_ptr> setting_list_t;
 class FGInputDevice;
 class FGInputEvent : public SGReferenced,FGCommonInput {
 public:
+
   /*
    * Constructor for the class. The arg node shall point
    * to the property corresponding to the <event>  node
@@ -110,6 +111,7 @@ public:
   static FGInputEvent * NewObject( FGInputDevice * device, SGPropertyNode_ptr node );
 
 protected:
+  virtual void fire( SGBinding * binding, FGEventData & eventData );
   /* A more or less meaningfull description of the event */
   string desc;
 
@@ -143,6 +145,9 @@ protected:
 class FGAxisEvent : public FGInputEvent {
 public:
   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:
   virtual void fire( FGEventData & eventData );
   double tolerance;
@@ -155,6 +160,20 @@ protected:
   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;
 
 /*
index 382a99c8aa0d2b9c5ef51997ae0d26a72e66d795..183c7b3ab805c319b84bee27b0c3de372d611ac6 100644 (file)
@@ -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()
 {
   if( fd != -1 ) return;
@@ -280,9 +285,38 @@ void FGLinuxInputDevice::Open()
     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" );
   }
+
+  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()
@@ -437,7 +471,6 @@ void FGLinuxEventInput::AddHalDevice( const char * udi )
 void FGLinuxEventInput::update( double dt )
 {
   FGEventInput::update( dt );
-
   // index the input devices by the associated fd and prepare
   // the pollfd array by filling in the file descriptor
   struct pollfd fds[input_devices.size()];
@@ -468,6 +501,9 @@ void FGLinuxEventInput::update( double dt )
 
         FGLinuxEventData eventData( event, dt, modifiers );
 
+        if( event.type == EV_ABS )
+          eventData.value = devicesByFd[fds[i].fd]->Normalize( event );
+
         // let the FGInputDevice handle the data
         devicesByFd[fds[i].fd]->HandleEvent( eventData );
       }
index 5f7a58117282597d27770f833507c8b46dca1bf0..3676c48cbb8ee3a37b657384d3ea09da7654a647 100644 (file)
@@ -56,9 +56,12 @@ public:
 
   int GetFd() { return fd; }
 
+  double Normalize( struct input_event & event );
 private:
   string devname;
   int fd;
+
+  map<unsigned int,input_absinfo> absinfo;
 };
 
 class FGLinuxEventInput : public FGEventInput {
@@ -71,6 +74,7 @@ public:
   void AddHalDevice( const char * udi );
 protected:
   LibHalContext *halcontext;
+
 };
 
 #endif