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