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