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