//
// $Id$
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include "FGEventInput.hxx"
#include <Main/fg_props.hxx>
#include <simgear/io/sg_file.hxx>
-#include <poll.h>
-#include <linux/input.h>
+#include <Scripting/NasalSys.hxx>
+
+FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
+ value(0.0)
+{
+ SGPropertyNode_ptr n;
+
+ if( (n = base->getNode( "value" )) != NULL ) {
+ valueNode = NULL;
+ value = n->getDoubleValue();
+ } else {
+ n = base->getNode( "property" );
+ if( n == NULL ) {
+ SG_LOG( SG_INPUT, SG_WARN, "Neither <value> nor <property> defined for event setting." );
+ } else {
+ valueNode = fgGetNode( n->getStringValue(), true );
+ }
+ }
+
+ if( (n = base->getChild("condition")) != NULL )
+ condition = sgReadCondition(base, n);
+ else
+ SG_LOG( SG_INPUT, SG_ALERT, "No condition for event setting." );
+}
+
+double FGEventSetting::GetValue()
+{
+ return valueNode == NULL ? value : valueNode->getDoubleValue();
+}
+
+bool FGEventSetting::Test()
+{
+ return condition == NULL ? true : condition->test();
+}
static inline bool StartsWith( string & s, const char * cp )
{
return s.compare( 0, strlen(cp), cp ) == 0;
}
-FGInputEvent * FGInputEvent::NewObject( SGPropertyNode_ptr node )
+FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
{
- string name = node->getStringValue( "name" );
+ string name = node->getStringValue( "name", "" );
if( StartsWith( name, "button-" ) )
- return new FGButtonEvent( node );
+ return new FGButtonEvent( device, node );
if( StartsWith( name, "rel-" ) )
- return new FGAxisEvent( node );
+ return new FGAxisEvent( device, node );
if( StartsWith( name, "abs-" ) )
- return new FGAxisEvent( node );
+ return new FGAxisEvent( device, node );
- return NULL;
+ return new FGInputEvent( device, node );
}
-FGInputEvent::FGInputEvent( SGPropertyNode_ptr node ) :
- lastDt(0.0)
+FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
+ device( aDevice ),
+ lastDt(0.0),
+ lastSettingValue(std::numeric_limits<float>::quiet_NaN())
{
- name = node->getStringValue( "name" );
- desc = node->getStringValue( "desc" );
+ name = node->getStringValue( "name", "" );
+ desc = node->getStringValue( "desc", "" );
intervalSec = node->getDoubleValue("interval-sec",0.0);
- string module = "event";
- read_bindings( node, bindings, KEYMOD_NONE, module );
+
+ read_bindings( node, bindings, KEYMOD_NONE, device->GetNasalModule() );
+
+ vector<SGPropertyNode_ptr> settingNodes = node->getChildren("setting");
+ for( vector<SGPropertyNode_ptr>::iterator it = settingNodes.begin(); it != settingNodes.end(); it++ )
+ settings.push_back( new FGEventSetting( *it ) );
}
FGInputEvent::~FGInputEvent()
{
}
+void FGInputEvent::update( double dt )
+{
+ for( setting_list_t::iterator it = settings.begin(); it != settings.end(); it++ ) {
+ if( (*it)->Test() ) {
+ double value = (*it)->GetValue();
+ if( value != lastSettingValue ) {
+ device->Send( GetName(), (*it)->GetValue() );
+ lastSettingValue = value;
+ }
+ }
+ }
+}
+
void FGInputEvent::fire( FGEventData & eventData )
{
lastDt += eventData.dt;
if( lastDt >= intervalSec ) {
- for( binding_list_t::iterator it = bindings[KEYMOD_NONE].begin(); it != bindings[KEYMOD_NONE].end(); it++ )
+ for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
(*it)->fire( eventData.value, 1.0 );
lastDt -= intervalSec;
}
}
-FGAxisEvent::FGAxisEvent( SGPropertyNode_ptr node ) :
- FGInputEvent( node )
+FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
+ FGInputEvent( device, node )
{
tolerance = node->getDoubleValue("tolerance", 0.002);
minRange = node->getDoubleValue("min-range", -1024.0);
FGInputEvent::fire( eventData );
}
-FGButtonEvent::FGButtonEvent( SGPropertyNode_ptr node ) :
- FGInputEvent( node )
+FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
+ FGInputEvent( device, node ),
+ repeatable(false),
+ lastState(false)
{
+ repeatable = node->getBoolValue("repeatable", repeatable);
}
void FGButtonEvent::fire( FGEventData & eventData )
{
- FGInputEvent::fire( eventData );
+ bool pressed = eventData.value > 0.0;
+ if (pressed) {
+ // The press event may be repeated.
+ if (!lastState || repeatable) {
+ SG_LOG( SG_INPUT, SG_DEBUG, "Button has been pressed" );
+ FGInputEvent::fire( eventData );
+ }
+ } else {
+ // The release event is never repeated.
+ if (lastState) {
+ SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
+ eventData.modifiers|=KEYMOD_RELEASED;
+ FGInputEvent::fire( eventData );
+ }
+ }
+
+ lastState = pressed;
}
FGInputDevice::~FGInputDevice()
{
+ FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
+ if (nas && deviceNode ) {
+ SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
+ if( nasal ) {
+ SGPropertyNode_ptr nasalClose = nasal->getNode("close");
+ if (nasalClose) {
+ const char *s = nasalClose->getStringValue();
+ nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s, strlen(s), deviceNode );
+ }
+ }
+ nas->deleteModule(nasalModule.c_str());
+ }
}
+void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
+{
+ deviceNode = aDeviceNode;
+
+ nasalModule = string("__event:") + GetName();
+
+ vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
+ for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ )
+ AddHandledEvent( FGInputEvent::NewObject( this, *it ) );
+
+ debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
+ grab = deviceNode->getBoolValue("grab", grab );
+
+ // TODO:
+ // add nodes for the last event:
+ // last-event/name [string]
+ // last-event/value [double]
+
+ SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
+ if (nasal) {
+ SGPropertyNode_ptr open = nasal->getNode("open");
+ if (open) {
+ const char *s = open->getStringValue();
+ FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
+ if (nas)
+ nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s, strlen(s), deviceNode );
+ }
+ }
+
+}
+
+void FGInputDevice::update( double dt )
+{
+ for( map<string,FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++ )
+ (*it).second->update( dt );
+}
+
void FGInputDevice::HandleEvent( FGEventData & eventData )
{
string eventName = TranslateEventName( eventData );
- cout << GetName() << " has event " << eventName << endl;
+ if( debugEvents )
+ cout << GetName() << " has event " <<
+ eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value << endl;
+
if( handledEvents.count( eventName ) > 0 ) {
handledEvents[ eventName ]->fire( eventData );
}
void FGEventInput::init( )
{
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
- SGPropertyNode * base = fgGetNode("/input/event", true);
+// SGPropertyNode * base = fgGetNode("/input/event", true);
}
{
}
-void FGEventInput::AddDevice( FGInputDevice * inputDevice )
+void FGEventInput::update( double dt )
+{
+ // call each associated device's update() method
+ for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
+ (*it).second->update( dt );
+}
+
+unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
{
SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
SGPropertyNode_ptr deviceNode = NULL;
// find a free index
unsigned index;
- for( index = 0; index < 1000; index++ )
+ for( index = 0; index < MAX_DEVICES; index++ )
if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
break;
- if( index == 1000 ) {
+ if( index == MAX_DEVICES ) {
SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
- return;
+ return INVALID_DEVICE_INDEX;
}
// create this node
// and copy the properties from the configuration tree
copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
+
}
if( deviceNode == NULL ) {
- SG_LOG(SG_INPUT, SG_WARN, "No configuration found for device " << inputDevice->GetName() );
- return;
+ SG_LOG(SG_INPUT, SG_DEBUG, "No configuration found for device " << inputDevice->GetName() );
+ delete inputDevice;
+ return INVALID_DEVICE_INDEX;
}
- vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
- for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ ) {
- FGInputEvent * p = FGInputEvent::NewObject( *it );
- if( p == NULL ) {
- SG_LOG(SG_INPUT, SG_WARN, "Unhandled event/name in " << inputDevice->GetName() );
- continue;
- }
- inputDevice->AddHandledEvent( p );
- }
+ inputDevice->Configure( deviceNode );
- // TODO:
- // add nodes for the last event:
- // last-event/name [string]
- // last-event/value [double]
-
try {
inputDevice->Open();
input_devices[ deviceNode->getIndex() ] = inputDevice;
}
catch( ... ) {
- SG_LOG(SG_INPUT, SG_WARN, "can't open InputDevice " << inputDevice->GetName() );
+ delete inputDevice;
+ SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName() );
+ return INVALID_DEVICE_INDEX;
}
+
+ SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName() );
+ return deviceNode->getIndex();
}
+
+void FGEventInput::RemoveDevice( unsigned index )
+{
+ // not fully implemented yet
+ SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
+ SGPropertyNode_ptr deviceNode = NULL;
+
+ FGInputDevice *inputDevice = input_devices[index];
+ if (inputDevice) {
+ input_devices.erase(index);
+ delete inputDevice;
+
+ }
+ deviceNode = baseNode->removeChild("device", index, false);
+}
+