X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInput%2FFGEventInput.cxx;h=8bf9f304e53bb2be03e22c04bbc1182008b3e78b;hb=d0a2fbba990c07608b813fa026126fe7ce52c552;hp=bf041367113ce8302a60e2e4f00a8cf83b4e9c2d;hpb=aea9c750f3f839817f8dcbdd7bc6bb4f81b97836;p=flightgear.git diff --git a/src/Input/FGEventInput.cxx b/src/Input/FGEventInput.cxx index bf0413671..8bf9f304e 100644 --- a/src/Input/FGEventInput.cxx +++ b/src/Input/FGEventInput.cxx @@ -20,64 +20,129 @@ // // $Id$ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include #include "FGEventInput.hxx" #include
#include -#include -#include +#include + +using simgear::PropertyList; + +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 nor 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; + return s.find( 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 FGRelAxisEvent( device, node ); if( StartsWith( name, "abs-" ) ) - return new FGAxisEvent( node ); + return new FGAbsAxisEvent( 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::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() ); + + PropertyList settingNodes = node->getChildren("setting"); + for( PropertyList::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++ ) - (*it)->fire( eventData.value, 1.0 ); + for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ ) + fire( *it, eventData ); lastDt -= intervalSec; } } -FGAxisEvent::FGAxisEvent( SGPropertyNode_ptr node ) : - FGInputEvent( node ) +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); @@ -90,27 +155,127 @@ 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 ); } -FGButtonEvent::FGButtonEvent( SGPropertyNode_ptr node ) : - FGInputEvent( node ) +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 ) : + 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 string s = nasalClose->getStringValue(); + nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode ); + } + } + nas->deleteModule(nasalModule.c_str()); + } } +void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode ) +{ + deviceNode = aDeviceNode; + + nasalModule = string("__event:") + GetName(); + + PropertyList eventNodes = deviceNode->getChildren( "event" ); + for( PropertyList::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 string s = open->getStringValue(); + FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal"); + if (nas) + nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode ); + } + } + +} + +void FGInputDevice::update( double dt ) +{ + for( map::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 ); } @@ -138,7 +303,7 @@ FGEventInput::~FGEventInput() void FGEventInput::init( ) { SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings"); - SGPropertyNode * base = fgGetNode("/input/event", true); +// SGPropertyNode * base = fgGetNode("/input/event", true); } @@ -146,7 +311,14 @@ void FGEventInput::postinit () { } -void FGEventInput::AddDevice( FGInputDevice * inputDevice ) +void FGEventInput::update( double dt ) +{ + // call each associated device's update() method + for( map::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; @@ -157,13 +329,13 @@ void FGEventInput::AddDevice( FGInputDevice * inputDevice ) // 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 @@ -171,33 +343,43 @@ void FGEventInput::AddDevice( FGInputDevice * inputDevice ) // 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 eventNodes = deviceNode->getChildren( "event" ); - for( vector::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); } +