]> git.mxchange.org Git - flightgear.git/blobdiff - src/Input/input.cxx
Added static port system and a new altimeter model connected to it.
[flightgear.git] / src / Input / input.cxx
index ebbc2a62e9ecb9583ada73fcd6de1c8e3294c1d0..93cad1dbadd33cdc0675bbe208d27b01402ce390 100644 (file)
@@ -143,13 +143,10 @@ FGBinding::fire () const
 }
 
 void
-FGBinding::fire (int x, int y) const
+FGBinding::fire (double offset, double max) const
 {
   if (test()) {
-    if (x >= 0)
-      _arg->setIntValue("x-pos", x);
-    if (y >= 0)
-      _arg->setIntValue("y-pos", y);
+    _arg->setDoubleValue("offset", offset/max);
     fire();
   }
 }
@@ -180,7 +177,6 @@ FGInput current_input;
 
 
 FGInput::FGInput ()
-  : _mouse_mode(0)
 {
   // no op
 }
@@ -196,6 +192,14 @@ FGInput::init ()
   _init_keyboard();
   _init_joystick();
   _init_mouse();
+
+  glutKeyboardFunc(GLUTkey);
+  glutKeyboardUpFunc(GLUTkeyup);
+  glutSpecialFunc(GLUTspecialkey);
+  glutSpecialUpFunc(GLUTspecialkeyup);
+  glutMouseFunc (GLUTmouse);
+  glutMotionFunc (GLUTmotion);
+  glutPassiveMotionFunc (GLUTmotion);
 }
 
 void
@@ -211,7 +215,7 @@ FGInput::unbind ()
 }
 
 void 
-FGInput::update (int dt)
+FGInput::update (double dt)
 {
   _update_keyboard();
   _update_joystick();
@@ -348,16 +352,90 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 void
 FGInput::doMouseClick (int b, int updown, int x, int y)
 {
-  std::cout << "Mouse click " << b << ',' << updown << std::endl;
   int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
 
-  _update_button(_mouse_bindings[0].buttons[b], modifiers, updown, x, y);
+  mouse &m = _mouse_bindings[0];
+  mouse_mode &mode = m.modes[m.current_mode];
+
+                               // Let the property manager know.
+  if (b >= 0 && b < MAX_MOUSE_BUTTONS)
+    m.mouse_button_nodes[b]->setBoolValue(updown == GLUT_DOWN);
+
+                               // Pass on to PUI and the panel if
+                               // requested, and return if one of
+                               // them consumes the event.
+  if (mode.pass_through) {
+    if (puMouse(b, updown, x, y))
+      return;
+    else if ((current_panel != 0) &&
+            current_panel->doMouseAction(b, updown, x, y))
+      return;
+  }
+
+                               // OK, PUI and the panel didn't want the click
+  if (b >= MAX_MOUSE_BUTTONS) {
+    SG_LOG(SG_INPUT, SG_ALERT, "Mouse button " << b
+          << " where only " << MAX_MOUSE_BUTTONS << " expected");
+    return;
+  }
+
+  _update_button(m.modes[m.current_mode].buttons[b], modifiers, 0 != updown, x, y);
 }
 
 void
 FGInput::doMouseMotion (int x, int y)
 {
-  // TODO
+  int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
+
+  int xsize = fgGetInt("/sim/startup/xsize", 800);
+  int ysize = fgGetInt("/sim/startup/ysize", 600);
+  mouse &m = _mouse_bindings[0];
+  if (m.current_mode < 0 || m.current_mode >= m.nModes)
+    return;
+  mouse_mode &mode = m.modes[m.current_mode];
+
+                               // Pass on to PUI if requested, and return
+                               // if PUI consumed the event.
+  if (mode.pass_through && puMouse(x, y))
+    return;
+
+                               // OK, PUI didn't want the event,
+                               // so we can play with it.
+  if (x != m.x) {
+    int delta = x - m.x;
+    for (unsigned int i = 0; i < mode.x_bindings[modifiers].size(); i++)
+      mode.x_bindings[modifiers][i]->fire(double(delta), double(xsize));
+  }
+  if (y != m.y) {
+    int delta = y - m.y;
+    for (unsigned int i = 0; i < mode.y_bindings[modifiers].size(); i++)
+      mode.y_bindings[modifiers][i]->fire(double(delta), double(ysize));
+  }
+
+                               // Constrain the mouse if requested
+  if (mode.constrained) {
+    bool need_warp = false;
+    if (x <= 0) {
+      x = xsize - 2;
+      need_warp = true;
+    } else if (x >= (xsize-1)) {
+      x = 1;
+      need_warp = true;
+    }
+
+    if (y <= 0) {
+      y = ysize - 2;
+      need_warp = true;
+    } else if (y >= (ysize-1)) {
+      y = 1;
+      need_warp = true;
+    }
+
+    if (need_warp)
+      glutWarpPointer(x, y);
+  }
+  m.x = x;
+  m.y = y;
 }
 
 void
@@ -371,7 +449,7 @@ FGInput::_init_keyboard ()
     key_nodes = fgGetNode("/input/keyboard", true);
   }
   
-  vector<SGPropertyNode *> keys = key_nodes->getChildren("key");
+  vector<SGPropertyNode_ptr> keys = key_nodes->getChildren("key");
   for (unsigned int i = 0; i < keys.size(); i++) {
     int index = keys[i]->getIndex();
     SG_LOG(SG_INPUT, SG_DEBUG, "Binding key " << index);
@@ -393,7 +471,7 @@ FGInput::_init_joystick ()
   }
 
   for (int i = 0; i < MAX_JOYSTICKS; i++) {
-    SGPropertyNode * js_node = js_nodes->getChild("js", i);
+    SGPropertyNode_ptr js_node = js_nodes->getChild("js", i);
     if (js_node == 0) {
       SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for joystick " << i);
       js_node = js_nodes->getChild("js", i, true);
@@ -403,6 +481,30 @@ FGInput::_init_joystick ()
     if (js->notWorking()) {
       SG_LOG(SG_INPUT, SG_WARN, "Joystick " << i << " not found");
       continue;
+    } else {
+#ifdef FG_PLIB_JOYSTICK_GETNAME
+      bool found_js = false;
+      const char * name = js->getName();
+      SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \""
+            << name << '"');
+      vector<SGPropertyNode_ptr> nodes = js_nodes->getChildren("js-named");
+      for (unsigned int i = 0; i < nodes.size(); i++) {
+       SGPropertyNode_ptr node = nodes[i];
+        vector<SGPropertyNode_ptr> name_nodes = node->getChildren("name");
+        for (unsigned int j = 0; j < name_nodes.size(); j++) {
+            const char * js_name = name_nodes[j]->getStringValue();
+            SG_LOG(SG_INPUT, SG_INFO, "  Trying \"" << js_name << '"');
+            if (!strcmp(js_name, name)) {
+                SG_LOG(SG_INPUT, SG_INFO, "  Found bindings");
+                js_node = node;
+                found_js = true;
+                break;
+            }
+        }
+        if (found_js)
+            break;
+      }
+#endif
     }
 #ifdef WIN32
     JOYCAPS jsCaps ;
@@ -468,7 +570,7 @@ FGInput::_init_joystick ()
     //
     // Initialize the buttons.
     //
-    char buf[8];
+    char buf[32];
     for (j = 0; j < nbuttons; j++) {
       sprintf(buf, "%d", j);
       SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << j);
@@ -484,6 +586,40 @@ FGInput::_init_joystick ()
   }
 }
 
+// 
+// Map of all known GLUT cursor names
+//
+struct {
+  const char * name;
+  int cursor;
+} mouse_cursor_map[] = {
+  { "right-arrow", GLUT_CURSOR_RIGHT_ARROW },
+  { "left-arrow", GLUT_CURSOR_LEFT_ARROW },
+  { "info", GLUT_CURSOR_INFO },
+  { "destroy", GLUT_CURSOR_DESTROY },
+  { "help", GLUT_CURSOR_HELP },
+  { "cycle", GLUT_CURSOR_CYCLE },
+  { "spray", GLUT_CURSOR_SPRAY },
+  { "wait", GLUT_CURSOR_WAIT },
+  { "text", GLUT_CURSOR_TEXT },
+  { "crosshair", GLUT_CURSOR_CROSSHAIR },
+  { "up-down", GLUT_CURSOR_UP_DOWN },
+  { "left-right", GLUT_CURSOR_LEFT_RIGHT },
+  { "top-side", GLUT_CURSOR_TOP_SIDE },
+  { "bottom-side", GLUT_CURSOR_BOTTOM_SIDE },
+  { "left-side", GLUT_CURSOR_LEFT_SIDE },
+  { "right-side", GLUT_CURSOR_RIGHT_SIDE },
+  { "top-left-corner", GLUT_CURSOR_TOP_LEFT_CORNER },
+  { "top-right-corner", GLUT_CURSOR_TOP_RIGHT_CORNER },
+  { "bottom-right-corner", GLUT_CURSOR_BOTTOM_RIGHT_CORNER },
+  { "bottom-left-corner", GLUT_CURSOR_BOTTOM_LEFT_CORNER },
+  { "inherit", GLUT_CURSOR_INHERIT },
+  { "none", GLUT_CURSOR_NONE },
+  { "full-crosshair", GLUT_CURSOR_FULL_CROSSHAIR },
+  { 0, 0 }
+};
+
+
 
 void
 FGInput::_init_mouse ()
@@ -496,20 +632,63 @@ FGInput::_init_mouse ()
     mouse_nodes = fgGetNode("/input/mice", true);
   }
 
+  int j;
   for (int i = 0; i < MAX_MICE; i++) {
-    const SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i);
-    _mouse_bindings[i].buttons = new button[MAX_MOUSE_BUTTONS];
-    if (mouse_node == 0) {
-      SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for mouse " << i);
-      mouse_node = mouse_nodes->getChild("mouse", i, true);
+    SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i, true);
+    mouse &m = _mouse_bindings[i];
+
+                               // Grab node pointers
+    char buf[64];
+    sprintf(buf, "/devices/status/mice/mouse[%d]/mode", i);
+    m.mode_node = fgGetNode(buf, true);
+    m.mode_node->setIntValue(0);
+    for (j = 0; j < MAX_MOUSE_BUTTONS; j++) {
+      sprintf(buf, "/devices/status/mice/mouse[%d]/button[%d]", i, j);
+      m.mouse_button_nodes[j] = fgGetNode(buf, true);
+      m.mouse_button_nodes[j]->setBoolValue(false);
     }
-    char buf[8];
-    for (int j = 0; j < MAX_MOUSE_BUTTONS; j++) {
-      sprintf(buf, "%d", j);
-      SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse button " << j);
-      _init_button(mouse_node->getChild("button", j),
-                  _mouse_bindings[i].buttons[j],
-                  buf);
+
+                               // Read all the modes
+    m.nModes = mouse_node->getIntValue("mode-count", 1);
+    m.modes = new mouse_mode[m.nModes];
+
+    for (int j = 0; j < m.nModes; j++) {
+      int k;
+
+                               // Read the mouse cursor for this mode
+      SGPropertyNode * mode_node = mouse_node->getChild("mode", j, true);
+      const char * cursor_name =
+       mode_node->getStringValue("cursor", "inherit");
+      m.modes[j].cursor = GLUT_CURSOR_INHERIT;
+      for (k = 0; mouse_cursor_map[k].name != 0; k++) {
+       if (!strcmp(mouse_cursor_map[k].name, cursor_name)) {
+         m.modes[j].cursor = mouse_cursor_map[k].cursor;
+         break;
+       }
+      }
+
+                               // Read other properties for this mode
+      m.modes[j].constrained = mode_node->getBoolValue("constrained", false);
+      m.modes[j].pass_through = mode_node->getBoolValue("pass-through", false);
+
+                               // Read the button bindings for this mode
+      m.modes[j].buttons = new button[MAX_MOUSE_BUTTONS];
+      char buf[32];
+      for (k = 0; k < MAX_MOUSE_BUTTONS; k++) {
+       sprintf(buf, "mouse button %d", k);
+       SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse button " << k);
+       _init_button(mode_node->getChild("button", k),
+                    m.modes[j].buttons[k],
+                    buf);
+      }
+
+                               // Read the axis bindings for this mode
+      _read_bindings(mode_node->getChild("x-axis", 0, true),
+                    m.modes[j].x_bindings,
+                    FG_MOD_NONE);
+      _read_bindings(mode_node->getChild("y-axis", 0, true),
+                    m.modes[j].y_bindings,
+                    FG_MOD_NONE);
     }
   }
 }
@@ -602,7 +781,20 @@ FGInput::_update_joystick ()
 void
 FGInput::_update_mouse ()
 {
-  // no-op
+  mouse &m = _mouse_bindings[0];
+  int mode =  m.mode_node->getIntValue();
+  if (mode != m.current_mode) {
+    m.current_mode = mode;
+    if (mode >= 0 && mode < m.nModes) {
+      glutSetCursor(m.modes[mode].cursor);
+      m.x = fgGetInt("/sim/startup/xsize", 800) / 2;
+      m.y = fgGetInt("/sim/startup/ysize", 600) / 2;
+      glutWarpPointer(m.x, m.y);
+    } else {
+      SG_LOG(SG_INPUT, SG_DEBUG, "Mouse mode " << mode << " out of range");
+      glutSetCursor(GLUT_CURSOR_INHERIT);
+    }
+  }
 }
 
 void
@@ -635,7 +827,7 @@ FGInput::_read_bindings (const SGPropertyNode * node,
                         int modifiers)
 {
   SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings");
-  vector<const SGPropertyNode *> bindings = node->getChildren("binding");
+  vector<SGPropertyNode_ptr> bindings = node->getChildren("binding");
   for (unsigned int i = 0; i < bindings.size(); i++) {
     SG_LOG(SG_INPUT, SG_DEBUG, "Reading binding "
           << bindings[i]->getStringValue("command"));
@@ -751,18 +943,50 @@ FGInput::joystick::~joystick ()
 }
 
 
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGInput::mouse_mode
+////////////////////////////////////////////////////////////////////////
+
+FGInput::mouse_mode::mouse_mode ()
+  : cursor(GLUT_CURSOR_INHERIT),
+    constrained(false),
+    pass_through(false),
+    buttons(0)
+{
+}
+
+FGInput::mouse_mode::~mouse_mode ()
+{
+                               // FIXME: memory leak
+//   for (int i = 0; i < FG_MOD_MAX; i++) {
+//     int j;
+//     for (j = 0; i < x_bindings[i].size(); j++)
+//       delete bindings[i][j];
+//     for (j = 0; j < y_bindings[i].size(); j++)
+//       delete bindings[i][j];
+//   }
+  delete [] buttons;
+}
+
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of FGInput::mouse
 ////////////////////////////////////////////////////////////////////////
 
 FGInput::mouse::mouse ()
+  : x(-1),
+    y(-1),
+    nModes(1),
+    current_mode(0),
+    modes(0)
 {
 }
 
 FGInput::mouse::~mouse ()
 {
-  delete [] buttons;
+  delete [] modes;
 }
 
 
@@ -827,14 +1051,12 @@ GLUTspecialkeyup(int k, int x, int y)
 void
 GLUTmouse (int button, int updown, int x, int y)
 {
-  current_input.doMouseClick(button, updown == GLUT_DOWN, x, y);
+  current_input.doMouseClick(button, updown, x, y);
 }
 
 void
 GLUTmotion (int x, int y)
 {
-  puMouse(x, y);
-//   glutPostRedisplay();
   current_input.doMouseMotion(x, y);
 }