# include <config.h>
#endif
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-
#include <simgear/compiler.h>
#include <math.h>
#include <ctype.h>
+#include <sstream>
-#include STL_FSTREAM
-#include STL_STRING
+#include <fstream>
+#include <string>
#include <vector>
#include <simgear/compiler.h>
#include <Scenery/scenery.hxx>
#include <Main/renderer.hxx>
-SG_USING_STD(ifstream);
-SG_USING_STD(string);
-SG_USING_STD(vector);
+using std::ifstream;
+using std::ostringstream;
+using std::string;
+using std::vector;
-void mouseClickHandler(int button, int updown, int x, int y);
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
void mouseMotionHandler(int x, int y);
void keyHandler(int key, int keymod, int mousex, int mousey);
// Local functions.
////////////////////////////////////////////////////////////////////////
+static int
+getModifiers ()
+{
+ return fgGetKeyModifiers() >> 1;
+}
+
static bool
getModShift ()
{
return bool(fgGetKeyModifiers() & KEYMOD_ALT);
}
+static bool
+getModMeta ()
+{
+ return bool(fgGetKeyModifiers() & KEYMOD_META);
+}
+
+static bool
+getModSuper ()
+{
+ return bool(fgGetKeyModifiers() & KEYMOD_SUPER);
+}
+
+static bool
+getModHyper ()
+{
+ return bool(fgGetKeyModifiers() & KEYMOD_HYPER);
+}
+
\f
////////////////////////////////////////////////////////////////////////
// Implementation of FGInput.
////////////////////////////////////////////////////////////////////////
-FGInput::FGInput ()
+FGInput::FGInput () :
+ _key_event(fgGetNode("/devices/status/keyboard/event", true))
{
if (default_input == 0)
default_input = this;
void
FGInput::init ()
{
- _init_keyboard();
_init_joystick();
_init_mouse();
FGInput::postinit ()
{
_postinit_joystick();
+ _postinit_keyboard();
}
void
FGInput::bind ()
{
+ fgTie("/devices/status/keyboard", getModifiers);
fgTie("/devices/status/keyboard/shift", getModShift);
fgTie("/devices/status/keyboard/ctrl", getModCtrl);
fgTie("/devices/status/keyboard/alt", getModAlt);
+ fgTie("/devices/status/keyboard/meta", getModMeta);
+ fgTie("/devices/status/keyboard/super", getModSuper);
+ fgTie("/devices/status/keyboard/hyper", getModHyper);
+
+ _key_event->tie("key", SGRawValuePointer<int>(&_key_code));
+ _key_event->tie("pressed", SGRawValuePointer<bool>(&_key_pressed));
+ _key_event->tie("modifier", SGRawValuePointer<int>(&_key_modifiers));
+ _key_event->tie("modifier/shift", SGRawValuePointer<bool>(&_key_shift));
+ _key_event->tie("modifier/ctrl", SGRawValuePointer<bool>(&_key_ctrl));
+ _key_event->tie("modifier/alt", SGRawValuePointer<bool>(&_key_alt));
+ _key_event->tie("modifier/meta", SGRawValuePointer<bool>(&_key_meta));
+ _key_event->tie("modifier/super", SGRawValuePointer<bool>(&_key_super));
+ _key_event->tie("modifier/hyper", SGRawValuePointer<bool>(&_key_hyper));
}
void
FGInput::unbind ()
{
+ fgUntie("/devices/status/keyboard");
fgUntie("/devices/status/keyboard/shift");
fgUntie("/devices/status/keyboard/ctrl");
fgUntie("/devices/status/keyboard/alt");
+ fgUntie("/devices/status/keyboard/meta");
+ fgUntie("/devices/status/keyboard/super");
+ fgUntie("/devices/status/keyboard/hyper");
+
+ _key_event->untie("key");
+ _key_event->untie("pressed");
+ _key_event->untie("modifier");
+ _key_event->untie("modifier/shift");
+ _key_event->untie("modifier/ctrl");
+ _key_event->untie("modifier/alt");
+ _key_event->untie("modifier/meta");
+ _key_event->untie("modifier/super");
+ _key_event->untie("modifier/hyper");
}
void
return;
}
+ _key_code = k;
+ _key_modifiers = modifiers >> 1;
+ _key_pressed = !bool(modifiers & KEYMOD_RELEASED);
+ _key_shift = bool(modifiers & KEYMOD_SHIFT);
+ _key_ctrl = bool(modifiers & KEYMOD_CTRL);
+ _key_alt = bool(modifiers & KEYMOD_ALT);
+ _key_meta = bool(modifiers & KEYMOD_META);
+ _key_super = bool(modifiers & KEYMOD_SUPER);
+ _key_hyper = bool(modifiers & KEYMOD_HYPER);
+ _key_event->fireValueChanged();
+ if (_key_code < 0)
+ return;
+
+ k = _key_code;
+ modifiers = _key_modifiers << 1;
+ if (!_key_pressed)
+ modifiers |= KEYMOD_RELEASED;
button &b = _key_bindings[k];
// Key pressed.
for (unsigned int i = 0; i < bindings.size(); i++)
bindings[i]->fire();
b.last_state = 0;
- } else {
- if (k >= 1 && k <= 26) {
- if (_key_bindings[k + '@'].last_state)
- doKey(k + '@', KEYMOD_RELEASED, x, y);
- if (_key_bindings[k + '`'].last_state)
- doKey(k + '`', KEYMOD_RELEASED, x, y);
- } else if (k >= 'A' && k <= 'Z') {
- if (_key_bindings[k - '@'].last_state)
- doKey(k - '@', KEYMOD_RELEASED, x, y);
- if (_key_bindings[tolower(k)].last_state)
- doKey(tolower(k), KEYMOD_RELEASED, x, y);
- } else if (k >= 'a' && k <= 'z') {
- if (_key_bindings[k - '`'].last_state)
- doKey(k - '`', KEYMOD_RELEASED, x, y);
- if (_key_bindings[toupper(k)].last_state)
- doKey(toupper(k), KEYMOD_RELEASED, x, y);
- }
}
}
}
void
-FGInput::doMouseClick (int b, int updown, int x, int y)
+FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
{
int modifiers = fgGetKeyModifiers();
}
if (mode.pass_through) {
- if (puMouse(b, updown, x, y))
+ if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
return;
- else if ((globals->get_current_panel() != 0) &&
+ else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
globals->get_current_panel()->getVisibility() &&
globals->get_current_panel()->doMouseAction(b, updown, x, y))
return;
- else if (fgHandle3DPanelMouseEvent(b, updown, x, y))
+ else if (0 <= x && 0 <= y && fgHandle3DPanelMouseEvent(b, updown, x, y))
return;
else {
// pui didn't want the click event so compute a
// scenegraph intersection point corresponding to the mouse click
if (updown == MOUSE_BUTTON_DOWN) {
- FGScenery* scenery = globals->get_scenery();
- SGVec3d start, dir;
// Get the list of hit callbacks. Take the first callback that
// accepts the mouse button press and ignore the rest of them
// That is they get sorted by distance and by scenegraph depth.
// The nearest one is the first one and the deepest
// (the most specialized one in the scenegraph) is the first.
- if (FGRenderer::getPickInfo(start, dir, x, y)) {
- std::vector<SGSceneryPick> pickList;
- scenery->pick(start, dir, pickList);
+ std::vector<SGSceneryPick> pickList;
+ if (FGRenderer::pick(pickList, ea)) {
std::vector<SGSceneryPick>::const_iterator i;
for (i = pickList.begin(); i != pickList.end(); ++i) {
if (i->callback->buttonPressed(b, i->info)) {
if (need_warp)
fgWarpMouse(x, y);
}
- m.x = x;
- m.y = y;
-}
-void
-FGInput::_init_keyboard ()
-{
- SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
- _module[0] = 0;
- SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
- if (key_nodes == 0) {
- SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");
- key_nodes = fgGetNode("/input/keyboard", true);
- }
-
- 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);
+ if (m.x != x)
+ fgSetInt("/devices/status/mice/mouse/x", m.x = x);
- _key_bindings[index].bindings->clear();
- _key_bindings[index].is_repeatable = keys[i]->getBoolValue("repeatable");
- _key_bindings[index].last_state = 0;
- _read_bindings(keys[i], _key_bindings[index].bindings, KEYMOD_NONE);
- }
+ if (m.y != y)
+ fgSetInt("/devices/status/mice/mouse/y", m.y = y);
}
}
+void
+FGInput::_postinit_keyboard()
+{
+ SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
+ _module = "__kbd";
+ SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
+ if (key_nodes == 0) {
+ SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");
+ key_nodes = fgGetNode("/input/keyboard", true);
+ }
+
+ FGNasalSys *nasalsys = (FGNasalSys *)globals->get_subsystem("nasal");
+ vector<SGPropertyNode_ptr> nasal = key_nodes->getChildren("nasal");
+ for (unsigned int j = 0; j < nasal.size(); j++) {
+ nasal[j]->setStringValue("module", _module.c_str());
+ nasalsys->handleCommand(nasal[j]);
+ }
+
+ 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);
+
+ _key_bindings[index].bindings->clear();
+ _key_bindings[index].is_repeatable = keys[i]->getBoolValue("repeatable");
+ _key_bindings[index].last_state = 0;
+ _read_bindings(keys[i], _key_bindings[index].bindings, KEYMOD_NONE);
+ }
+}
+
+
void
FGInput::_postinit_joystick()
{
//
// Initialize nasal groups.
//
- string init;
- init = "this=\"" + string(js_node->getPath()) + "\"";
- sprintf(_module, "__js%d", i);
- nasalsys->createModule(_module, _module, init.c_str(), init.size());
+ ostringstream str;
+ str << "__js" << i;
+ _module = str.str();
+ nasalsys->createModule(_module.c_str(), _module.c_str(), "", 0);
vector<SGPropertyNode_ptr> nasal = js_node->getChildren("nasal");
unsigned int j;
for (j = 0; j < nasal.size(); j++) {
- nasal[j]->setStringValue("module", _module);
+ nasal[j]->setStringValue("module", _module.c_str());
nasalsys->handleCommand(nasal[j]);
}
FGInput::_init_mouse ()
{
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse bindings");
- _module[0] = 0;
+ _module = "";
SGPropertyNode * mouse_nodes = fgGetNode("/input/mice");
if (mouse_nodes == 0) {
void
FGInput::_update_joystick (double dt)
{
- int modifiers = KEYMOD_NONE; // FIXME: any way to get the real ones?
- int buttons;
- // float js_val, diff;
float axis_values[MAX_JOYSTICK_AXES];
+ int modifiers = fgGetKeyModifiers();
+ int buttons;
- int i;
- int j;
-
- for ( i = 0; i < MAX_JOYSTICKS; i++) {
+ for (int i = 0; i < MAX_JOYSTICKS; i++) {
jsJoystick * js = _joystick_bindings[i].js;
if (js == 0 || js->notWorking())
js->read(&buttons, axis_values);
// Fire bindings for the axes.
- for ( j = 0; j < _joystick_bindings[i].naxes; j++) {
+ for (int j = 0; j < _joystick_bindings[i].naxes; j++) {
axis &a = _joystick_bindings[i].axes[j];
-
+
// 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) {
-// SG_LOG(SG_INPUT, SG_DEBUG, "Axis " << j << " has moved");
a.last_value = axis_values[j];
-// SG_LOG(SG_INPUT, SG_DEBUG, "There are "
-// << a.bindings[modifiers].size() << " bindings");
- for (unsigned int k = 0; k < a.bindings[modifiers].size(); k++)
- a.bindings[modifiers][k]->fire(axis_values[j]);
+ for (unsigned int k = 0; k < a.bindings[KEYMOD_NONE].size(); k++)
+ a.bindings[KEYMOD_NONE][k]->fire(axis_values[j]);
}
-
+
// do we have to emulate axis buttons?
a.last_dt += dt;
if(a.last_dt >= a.interval_sec) {
modifiers,
axis_values[j] < a.low_threshold,
-1, -1);
-
+
if (a.high.bindings[modifiers].size())
_update_button(_joystick_bindings[i].axes[j].high,
modifiers,
}
// Fire bindings for the buttons.
- for (j = 0; j < _joystick_bindings[i].nbuttons; j++) {
+ for (int j = 0; j < _joystick_bindings[i].nbuttons; j++) {
button &b = _joystick_bindings[i].buttons[j];
b.last_dt += dt;
if(b.last_dt >= b.interval_sec) {
if ( fgGetBool( "/sim/mouse/hide-cursor", true ) ) {
if ( m.x != m.save_x || m.y != m.save_y ) {
m.timeout = fgGetDouble( "/sim/mouse/cursor-timeout-sec", 10.0 );
- fgSetMouseCursor(m.modes[mode].cursor);
+ if (fgGetMouseCursor() == MOUSE_CURSOR_NONE)
+ fgSetMouseCursor(m.modes[mode].cursor);
} else {
m.timeout -= dt;
if ( m.timeout <= 0.0 ) {
const char *cmd = bindings[i]->getStringValue("command");
SG_LOG(SG_INPUT, SG_DEBUG, "Reading binding " << cmd);
- if (!strcmp(cmd, "nasal") && _module[0])
- bindings[i]->setStringValue("module", _module);
+ if (!strcmp(cmd, "nasal") && !_module.empty())
+ bindings[i]->setStringValue("module", _module.c_str());
binding_list[modifiers].push_back(new SGBinding(bindings[i], globals->get_props()));
}
if (node->getChild("mod-alt") != 0)
_read_bindings(node->getChild("mod-alt"), binding_list,
modifiers|KEYMOD_ALT);
+
+ if (node->getChild("mod-meta") != 0)
+ _read_bindings(node->getChild("mod-meta"), binding_list,
+ modifiers|KEYMOD_META);
+
+ if (node->getChild("mod-super") != 0)
+ _read_bindings(node->getChild("mod-super"), binding_list,
+ modifiers|KEYMOD_SUPER);
+
+ if (node->getChild("mod-hyper") != 0)
+ _read_bindings(node->getChild("mod-hyper"), binding_list,
+ modifiers|KEYMOD_HYPER);
}
FGInput::mouse::mouse ()
: x(-1),
y(-1),
+ save_x(-1),
+ save_y(-1),
nModes(1),
current_mode(0),
modes(0)
default_input->doKey(key, keymod, mousex, mousey);
}
-void mouseClickHandler(int button, int updown, int x, int y)
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
{
if(default_input)
- default_input->doMouseClick(button, updown, x, y);
+ default_input->doMouseClick(button, updown, x, y, mainWindow, ea);
}
void mouseMotionHandler(int x, int y)