]> git.mxchange.org Git - flightgear.git/blobdiff - src/Input/FGJoystickInput.cxx
autopilot: Introduce virtual dtor.
[flightgear.git] / src / Input / FGJoystickInput.cxx
index cf7cc3319535d6a8db22db489e1623749a242bd5..041fcc2e10bb9824f0d9457f0f83e304b7d9402e 100644 (file)
 //
 // $Id$
 
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include "FGJoystickInput.hxx"
+
+#include <simgear/props/props_io.hxx>
 #include "FGDeviceConfigurationMap.hxx"
 #include <Main/fg_props.hxx>
 #include <Scripting/NasalSys.hxx>
+#include <boost/foreach.hpp>
 
 using simgear::PropertyList;
 
@@ -49,16 +56,22 @@ FGJoystickInput::joystick::joystick ()
     naxes(0),
     nbuttons(0),
     axes(0),
-    buttons(0)
+    buttons(0),
+    predefined(true)
 {
 }
 
 FGJoystickInput::joystick::~joystick ()
 {
-//  delete js? why not?
-//   delete js;
+  //  delete js? no, since js == this - and we're in the destructor already.
   delete[] axes;
   delete[] buttons;
+  jsnum = 0;
+  js = NULL;
+  naxes = 0;
+  nbuttons = 0;
+  axes = NULL;
+  buttons = NULL;
 }
 
 
@@ -68,15 +81,29 @@ FGJoystickInput::FGJoystickInput()
 
 FGJoystickInput::~FGJoystickInput()
 {
+    _remove(true);
 }
 
+void FGJoystickInput::_remove(bool all)
+{
+    SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
+
+    for (int i = 0; i < MAX_JOYSTICKS; i++)
+    {
+        // do not remove predefined joysticks info on reinit
+        if ((all)||(!bindings[i].predefined))
+            js_nodes->removeChild("js", i, false);
+        if (bindings[i].js)
+            delete bindings[i].js;
+        bindings[i].js = NULL;
+    }
+}
 
 void FGJoystickInput::init()
 {
   jsInit();
-                                // TODO: zero the old bindings first.
   SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings");
-  SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
+  SGPropertyNode_ptr js_nodes = fgGetNode("/input/joysticks", true);
 
   FGDeviceConfigurationMap configMap("Input/Joysticks", js_nodes, "js-named");
 
@@ -96,6 +123,7 @@ void FGJoystickInput::init()
       SG_LOG(SG_INPUT, SG_INFO, "Using existing bindings for joystick " << i);
 
     } else {
+      bindings[i].predefined = false;
       SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \"" << name << '"');
       SGPropertyNode_ptr named;
 
@@ -121,8 +149,7 @@ void FGJoystickInput::init()
 
 void FGJoystickInput::reinit() {
   SG_LOG(SG_INPUT, SG_DEBUG, "Re-Initializing joystick bindings");
-  SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
-  js_nodes->removeChildren("js", false);
+  _remove(false);
   FGJoystickInput::init();
   FGJoystickInput::postinit();
 }
@@ -171,7 +198,7 @@ void FGJoystickInput::postinit()
     //
     // Initialize nasal groups.
     //
-    ostringstream str;
+    std::ostringstream str;
     str << "__js" << i;
     string module = str.str();
     nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
@@ -195,10 +222,19 @@ void FGJoystickInput::postinit()
       if (num_node != 0) {
           n_axis = num_node->getIntValue(TGT_PLATFORM, -1);
 
+        #ifdef SG_MAC
+          // Mac falls back to Unix by default - avoids specifying many
+          // duplicate <mac> entries in joystick config files
+          if (n_axis < 0) {
+              n_axis = num_node->getIntValue("unix", -1);
+          }
+        #endif
+          
           // Silently ignore platforms that are not specified within the
           // <number></number> section
-          if (n_axis < 0)
-             continue;
+          if (n_axis < 0) {
+              continue;
+          }
       }
 
       if (n_axis >= naxes) {
@@ -230,30 +266,27 @@ void FGJoystickInput::postinit()
     // Initialize the buttons.
     //
     PropertyList buttons = js_node->getChildren("button");
-    char buf[32];
-    for (j = 0; j < buttons.size() && j < nbuttons; j++) {
-      const SGPropertyNode * button_node = buttons[j];
-      const SGPropertyNode * num_node = button_node->getChild("number");
+    BOOST_FOREACH( SGPropertyNode * button_node, buttons ) {
       size_t n_but = button_node->getIndex();
-      if (num_node != 0) {
+
+      const SGPropertyNode * num_node = button_node->getChild("number");
+      if (NULL != num_node)
           n_but = num_node->getIntValue(TGT_PLATFORM,n_but);
-      }
 
       if (n_but >= nbuttons) {
           SG_LOG(SG_INPUT, SG_DEBUG, "Dropping bindings for button " << n_but);
           continue;
       }
 
-      sprintf(buf, "%u", (unsigned)n_but);
-      SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << n_but);
-      bindings[i].buttons[n_but].init(button_node, buf, module );
+      std::ostringstream buf;
+      buf << (unsigned)n_but;
 
-      // get interval-sec property
+      SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << buf.str());
       FGButton &b = bindings[i].buttons[n_but];
-      if (button_node != 0) {
-        b.interval_sec = button_node->getDoubleValue("interval-sec",0.0);
-        b.last_dt = 0.0;
-      }
+      b.init(button_node, buf.str(), module );
+      // get interval-sec property
+      b.interval_sec = button_node->getDoubleValue("interval-sec",0.0);
+      b.last_dt = 0.0;
     }
 
     js->setMinRange(minRange);
@@ -285,7 +318,9 @@ void FGJoystickInput::update( double dt )
                                 // Do nothing if the axis position
                                 // is unchanged; only a change in
                                 // position fires the bindings.
-      if (fabs(axis_values[j] - a.last_value) > a.tolerance) {
+                                // But only if there are bindings
+      if (fabs(axis_values[j] - a.last_value) > a.tolerance
+         && a.bindings[KEYMOD_NONE].size() > 0 ) {
         a.last_value = axis_values[j];
         for (unsigned int k = 0; k < a.bindings[KEYMOD_NONE].size(); k++)
           a.bindings[KEYMOD_NONE][k]->fire(axis_values[j]);
@@ -309,7 +344,7 @@ void FGJoystickInput::update( double dt )
       FGButton &b = bindings[i].buttons[j];
       b.last_dt += dt;
       if(b.last_dt >= b.interval_sec) {
-        bindings[i].buttons[j].update( modifiers, (buttons & (1 << j)) > 0 );
+        bindings[i].buttons[j].update( modifiers, (buttons & (1u << j)) > 0 );
         b.last_dt -= b.interval_sec;
       }
     }