]> git.mxchange.org Git - flightgear.git/blob - src/Input/FGEventInput.cxx
Avoid "using..." in header files.
[flightgear.git] / src / Input / FGEventInput.cxx
1 // FGEventInput.cxx -- handle event driven input devices
2 //
3 // Written by Torsten Dreyer, started July 2009.
4 //
5 // Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <cstring>
28 #include "FGEventInput.hxx"
29 #include <Main/fg_props.hxx>
30 #include <simgear/io/sg_file.hxx>
31 #include <simgear/props/props_io.hxx>
32 #include <Scripting/NasalSys.hxx>
33
34 using simgear::PropertyList;
35 using std::cout;
36 using std::endl;
37 using std::map;
38
39 FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
40   value(0.0)
41 {
42   SGPropertyNode_ptr n;
43
44   if( (n = base->getNode( "value" )) != NULL ) {  
45     valueNode = NULL;
46     value = n->getDoubleValue();
47   } else {
48     n = base->getNode( "property" );
49     if( n == NULL ) {
50       SG_LOG( SG_INPUT, SG_WARN, "Neither <value> nor <property> defined for event setting." );
51     } else {
52       valueNode = fgGetNode( n->getStringValue(), true );
53     }
54   }
55
56   if( (n = base->getChild("condition")) != NULL )
57     condition = sgReadCondition(base, n);
58   else
59     SG_LOG( SG_INPUT, SG_ALERT, "No condition for event setting." );
60 }
61
62 double FGEventSetting::GetValue()
63 {
64   return valueNode == NULL ? value : valueNode->getDoubleValue();
65 }
66
67 bool FGEventSetting::Test()
68 {
69   return condition == NULL ? true : condition->test();
70 }
71
72 static inline bool StartsWith( string & s, const char * cp )
73 {
74   return s.find( cp ) == 0;
75 }
76
77 FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
78 {
79   string name = node->getStringValue( "name", "" );
80   if( StartsWith( name, "button-" ) )
81     return new FGButtonEvent( device, node );
82
83   if( StartsWith( name, "rel-" ) )
84     return new FGRelAxisEvent( device, node );
85
86   if( StartsWith( name, "abs-" ) )
87     return new FGAbsAxisEvent( device, node );
88
89   return new FGInputEvent( device, node );
90 }
91
92 FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
93   device( aDevice ),
94   lastDt(0.0), 
95   lastSettingValue(std::numeric_limits<float>::quiet_NaN())
96 {
97   name = node->getStringValue( "name", "" );
98   desc = node->getStringValue( "desc", "" );
99   intervalSec = node->getDoubleValue("interval-sec",0.0);
100   
101   read_bindings( node, bindings, KEYMOD_NONE, device->GetNasalModule() );
102
103   PropertyList settingNodes = node->getChildren("setting");
104   for( PropertyList::iterator it = settingNodes.begin(); it != settingNodes.end(); ++it )
105     settings.push_back( new FGEventSetting( *it ) );
106 }
107
108 FGInputEvent::~FGInputEvent()
109 {
110 }
111
112 void FGInputEvent::update( double dt )
113 {
114   for( setting_list_t::iterator it = settings.begin(); it != settings.end(); ++it ) {
115     if( (*it)->Test() ) {
116       double value = (*it)->GetValue();
117       if( value != lastSettingValue ) {
118         device->Send( GetName(), (*it)->GetValue() );
119         lastSettingValue = value;
120       }
121     }
122   }
123 }
124
125 void FGInputEvent::fire( FGEventData & eventData )
126 {
127   lastDt += eventData.dt;
128   if( lastDt >= intervalSec ) {
129
130     for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); ++it )
131       fire( *it, eventData );
132
133     lastDt -= intervalSec;
134   }
135 }
136
137 void FGInputEvent::fire( SGBinding * binding, FGEventData & eventData )
138 {
139   binding->fire();
140 }
141
142
143
144 FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
145   FGInputEvent( device, node )
146 {
147   tolerance = node->getDoubleValue("tolerance", 0.002);
148   minRange = node->getDoubleValue("min-range", 0.0 );
149   maxRange = node->getDoubleValue("max-range", 0.0 );
150   center = node->getDoubleValue("center", 0.0);
151   deadband = node->getDoubleValue("dead-band", 0.0);
152   lowThreshold = node->getDoubleValue("low-threshold", -0.9);
153   highThreshold = node->getDoubleValue("high-threshold", 0.9);
154   lastValue = 9999999;
155 }
156
157 void FGAxisEvent::fire( FGEventData & eventData )
158 {
159   if (fabs( eventData.value - lastValue) < tolerance)
160     return;
161   lastValue = eventData.value;
162
163   // We need a copy of the  FGEventData struct to set the new value and to avoid side effects
164   FGEventData ed = eventData;
165
166   if( fabs(ed.value) < deadband )
167     ed.value = 0.0;
168
169   if( minRange != maxRange )
170     ed.value = 2.0*(eventData.value-minRange)/(maxRange-minRange)-1.0;
171
172   FGInputEvent::fire( ed );
173 }
174
175 void FGAbsAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
176 {
177   // sets the "setting" node
178   binding->fire( eventData.value );
179 }
180
181 FGRelAxisEvent::FGRelAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) : 
182   FGAxisEvent( device, node ) 
183 {
184   // relative axes can't use tolerance
185   tolerance = 0.0;
186 }
187
188 void FGRelAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
189 {
190   // sets the "offset" node
191   binding->fire( eventData.value, 1.0 );
192 }
193
194 FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
195   FGInputEvent( device, node ),
196   repeatable(false),
197   lastState(false)
198 {
199   repeatable = node->getBoolValue("repeatable", repeatable);
200 }
201
202 void FGButtonEvent::fire( FGEventData & eventData )
203 {
204   bool pressed = eventData.value > 0.0;
205   if (pressed) {
206     // The press event may be repeated.
207     if (!lastState || repeatable) {
208       SG_LOG( SG_INPUT, SG_DEBUG, "Button has been pressed" );
209       FGInputEvent::fire( eventData );
210     }
211   } else {
212     // The release event is never repeated.
213     if (lastState) {
214       SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
215       eventData.modifiers|=KEYMOD_RELEASED;
216       FGInputEvent::fire( eventData );
217     }
218   }
219           
220   lastState = pressed;
221 }
222
223 FGInputDevice::~FGInputDevice()
224 {
225   FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
226   if (nas && deviceNode ) {
227     SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
228     if( nasal ) {
229       SGPropertyNode_ptr nasalClose = nasal->getNode("close");
230       if (nasalClose) {
231         const string s = nasalClose->getStringValue();
232         nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
233       }
234     }
235     nas->deleteModule(nasalModule.c_str());
236   }
237
238
239 void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
240 {
241   deviceNode = aDeviceNode;
242
243   nasalModule = string("__event:") + GetName();
244
245   PropertyList eventNodes = deviceNode->getChildren( "event" );
246   for( PropertyList::iterator it = eventNodes.begin(); it != eventNodes.end(); ++it )
247     AddHandledEvent( FGInputEvent::NewObject( this, *it ) );
248
249   debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
250   grab = deviceNode->getBoolValue("grab", grab );
251
252   // TODO:
253   // add nodes for the last event:
254   // last-event/name [string]
255   // last-event/value [double]
256
257   SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
258   if (nasal) {
259     SGPropertyNode_ptr open = nasal->getNode("open");
260     if (open) {
261       const string s = open->getStringValue();
262       FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
263       if (nas)
264         nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
265     }
266   }
267
268 }
269
270 void FGInputDevice::update( double dt )
271 {
272   for( map<string,FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++ )
273     (*it).second->update( dt );
274 }
275
276 void FGInputDevice::HandleEvent( FGEventData & eventData )
277 {
278   string eventName = TranslateEventName( eventData );  
279   if( debugEvents )
280     cout << GetName() << " has event " << 
281     eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value << endl;
282
283   if( handledEvents.count( eventName ) > 0 ) {
284     handledEvents[ eventName ]->fire( eventData );
285   }
286 }
287
288 void FGInputDevice::SetName( string name )
289 {
290   this->name = name; 
291 }
292
293 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
294
295 FGEventInput::FGEventInput() : 
296   configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
297 {
298 }
299
300 FGEventInput::~FGEventInput()
301 {
302   for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); ++it )
303     delete (*it).second;
304   input_devices.clear();
305 }
306
307 void FGEventInput::init( )
308 {
309   SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
310 //  SGPropertyNode * base = fgGetNode("/input/event", true);
311
312 }
313
314 void FGEventInput::postinit ()
315 {
316 }
317
318 void FGEventInput::update( double dt )
319 {
320   // call each associated device's update() method
321   for( map<int,FGInputDevice*>::iterator it =  input_devices.begin(); it != input_devices.end(); ++it )
322     (*it).second->update( dt );
323 }
324
325 unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
326 {
327   SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
328   SGPropertyNode_ptr deviceNode = NULL;
329
330   // look for configuration in the device map
331   if( configMap.count( inputDevice->GetName() ) > 0 ) {
332     // found - copy to /input/event/device[n]
333
334     // find a free index
335     unsigned index;
336     for( index = 0; index < MAX_DEVICES; index++ )
337       if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
338         break;
339
340     if( index == MAX_DEVICES ) {
341       SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
342       return INVALID_DEVICE_INDEX;
343     }
344
345     // create this node 
346     deviceNode = baseNode->getNode( "device", index, true );
347
348     // and copy the properties from the configuration tree
349     copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
350
351   }
352
353   if( deviceNode == NULL ) {
354     SG_LOG(SG_INPUT, SG_DEBUG, "No configuration found for device " << inputDevice->GetName() );
355     delete  inputDevice;
356     return INVALID_DEVICE_INDEX;
357   }
358
359   inputDevice->Configure( deviceNode );
360
361   try { 
362     inputDevice->Open();
363     input_devices[ deviceNode->getIndex() ] = inputDevice;
364   }
365   catch( ... ) {
366     delete  inputDevice;
367     SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName()  );
368     return INVALID_DEVICE_INDEX;
369   }
370
371   SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName()  );
372   return deviceNode->getIndex();
373 }
374
375 void FGEventInput::RemoveDevice( unsigned index )
376 {
377   // not fully implemented yet
378   SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
379   SGPropertyNode_ptr deviceNode = NULL;
380
381   FGInputDevice *inputDevice = input_devices[index];
382   if (inputDevice) {
383     input_devices.erase(index);
384     delete inputDevice;
385     
386   }
387   deviceNode = baseNode->removeChild("device", index, false);
388 }
389