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