1
0
Fork 0

1. Fixed FGInput bug preventing same key from being bound separately

with different modifiers (the format of the key bindings has changed
again slightly, adding a <code>..</code> element; see keyboard.xml for
details).

2. Modified FGInput to try default modifiers for ctrl, shift, and alt
when the initial bindings fail (i.e. you don't have to specify
mod-shift explicitly for upper-case 'P' any more).

3. Fixed problems with properties and panel reloading reported by
Martin Dressler and John Check.

4. Updated preferences.xml to get rid of obsolete references to
/controls/brakes/left and /controls/brakes/right (as reported by John
Check).


There were also two non-bugs reported by John Check:

(a) Differential braking doesn't work (John was using the obsolete
properties from #4 above).

(b) Duplicates show up in the property tree using the telnet interface
(the property tree doesn't show indices, and John was seeing separate
entries for each possible engine, etc.).
This commit is contained in:
curt 2001-05-29 22:31:04 +00:00
parent 876e9c60fd
commit 5893de13ff
3 changed files with 294 additions and 273 deletions

View file

@ -135,7 +135,8 @@ FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
_mouseInstrument(0),
_winx(window_x), _winy(window_y), _winw(window_w), _winh(window_h),
_width(_winw), _height(int(_winh * 0.5768 + 1)),
_x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232))
_x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232)),
_bound(false)
{
setVisibility(fgPanelVisible());
}
@ -146,7 +147,8 @@ FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
*/
FGPanel::~FGPanel ()
{
unbind();
if (_bound)
unbind();
for (instrument_list_type::iterator it = _instruments.begin();
it != _instruments.end();
it++) {
@ -185,6 +187,7 @@ FGPanel::bind ()
fgTie("/sim/panel/visibility", &_visibility);
fgTie("/sim/panel/x-offset", &_x_offset);
fgTie("/sim/panel/y-offset", &_y_offset);
_bound = true;
}
@ -197,6 +200,7 @@ FGPanel::unbind ()
fgUntie("/sim/panel/visibility");
fgUntie("/sim/panel/x-offset");
fgUntie("/sim/panel/y-offset");
_bound = false;
}

View file

@ -180,6 +180,7 @@ private:
int _x_offset;
int _y_offset;
int _view_height;
bool _bound;
ssgTexture * _bg;
// List of instruments in panel.

View file

@ -71,152 +71,152 @@ SG_USING_STD(string);
////////////////////////////////////////////////////////////////////////
FGBinding::FGBinding ()
: _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
: _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
{
}
FGBinding::FGBinding (const SGPropertyNode * node)
: _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
: _action(ACTION_NONE), _node(0), _adjust_step(0), _assign_value(0)
{
read(node);
read(node);
}
FGBinding::~FGBinding ()
{
// no op
// no op
}
void
FGBinding::setAction (Action action)
{
_action = action;
_action = action;
}
void
FGBinding::setProperty (SGPropertyNode * node)
{
_node = node;
_node = node;
}
void
FGBinding::setAdjustStep (const SGValue * step)
{
_adjust_step = step;
_adjust_step = step;
}
void
FGBinding::setAssignValue (const SGValue * value)
{
_assign_value = value;
_assign_value = value;
}
void
FGBinding::read (const SGPropertyNode * node)
{
if (node->hasValue("action")) {
string action = node->getStringValue("action");
if (action == "none")
_action = ACTION_NONE;
else if (action == "switch")
_action = ACTION_SWITCH;
else if (action == "adjust")
_action = ACTION_ADJUST;
else if (action == "assign")
_action = ACTION_ASSIGN;
else
SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unrecognized action type "
<< action);
}
if (node->hasValue("action")) {
string action = node->getStringValue("action");
if (action == "none")
_action = ACTION_NONE;
else if (action == "switch")
_action = ACTION_SWITCH;
else if (action == "adjust")
_action = ACTION_ADJUST;
else if (action == "assign")
_action = ACTION_ASSIGN;
else
SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unrecognized action type "
<< action);
}
if (node->hasValue("control"))
_node = fgGetNode(node->getStringValue("control"), true);
if (node->hasValue("control"))
_node = fgGetNode(node->getStringValue("control"), true);
if (node->hasValue("step"))
_adjust_step = node->getChild("step")->getValue();
if (node->hasValue("step"))
_adjust_step = node->getChild("step")->getValue();
if (node->hasValue("value"))
_assign_value = node->getChild("value")->getValue();
if (node->hasValue("value"))
_assign_value = node->getChild("value")->getValue();
}
void
FGBinding::fire () const
{
if (_node == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No control property attached to binding");
return;
if (_node == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No control property attached to binding");
return;
}
switch (_action) {
case ACTION_NONE:
break;
case ACTION_SWITCH:
_node->setBoolValue(!_node->getBoolValue());
break;
case ACTION_ADJUST:
if (_adjust_step == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No step provided for adjust binding");
break;
}
switch (_action) {
case ACTION_NONE:
break;
case ACTION_SWITCH:
_node->setBoolValue(!_node->getBoolValue());
break;
case ACTION_ADJUST:
if (_adjust_step == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No step provided for adjust binding");
break;
}
switch (_node->getType()) {
case SGValue::BOOL:
if (_adjust_step->getBoolValue())
_node->setBoolValue(!_node->getBoolValue());
break;
case SGValue::INT:
_node->setIntValue(_node->getIntValue() + _adjust_step->getIntValue());
break;
case SGValue::LONG:
_node->setLongValue(_node->getLongValue() + _adjust_step->getLongValue());
break;
case SGValue::FLOAT:
_node->setFloatValue(_node->getFloatValue()
+ _adjust_step->getFloatValue());
break;
case SGValue::DOUBLE:
case SGValue::UNKNOWN: // force to double
_node->setDoubleValue(_node->getDoubleValue()
+ _adjust_step->getDoubleValue());
break;
case SGValue::STRING:
SG_LOG(SG_INPUT, SG_ALERT, "Cannot increment or decrement string value"
<< _node->getStringValue());
break;
}
break;
case ACTION_ASSIGN:
if (_assign_value == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No value provided for assign binding");
break;
}
switch (_node->getType()) {
case SGValue::BOOL:
_node->setBoolValue(_assign_value->getBoolValue());
break;
case SGValue::INT:
_node->setIntValue(_assign_value->getIntValue());
break;
case SGValue::LONG:
_node->setLongValue(_assign_value->getLongValue());
break;
case SGValue::FLOAT:
_node->setFloatValue(_assign_value->getFloatValue());
break;
case SGValue::DOUBLE:
_node->setDoubleValue(_assign_value->getDoubleValue());
break;
case SGValue::STRING:
_node->setStringValue(_assign_value->getStringValue());
break;
case SGValue::UNKNOWN:
_node->setUnknownValue(_assign_value->getStringValue());
break;
}
break;
switch (_node->getType()) {
case SGValue::BOOL:
if (_adjust_step->getBoolValue())
_node->setBoolValue(!_node->getBoolValue());
break;
case SGValue::INT:
_node->setIntValue(_node->getIntValue() + _adjust_step->getIntValue());
break;
case SGValue::LONG:
_node->setLongValue(_node->getLongValue() + _adjust_step->getLongValue());
break;
case SGValue::FLOAT:
_node->setFloatValue(_node->getFloatValue()
+ _adjust_step->getFloatValue());
break;
case SGValue::DOUBLE:
case SGValue::UNKNOWN: // force to double
_node->setDoubleValue(_node->getDoubleValue()
+ _adjust_step->getDoubleValue());
break;
case SGValue::STRING:
SG_LOG(SG_INPUT, SG_ALERT, "Cannot increment or decrement string value"
<< _node->getStringValue());
break;
}
break;
case ACTION_ASSIGN:
if (_assign_value == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No value provided for assign binding");
break;
}
switch (_node->getType()) {
case SGValue::BOOL:
_node->setBoolValue(_assign_value->getBoolValue());
break;
case SGValue::INT:
_node->setIntValue(_assign_value->getIntValue());
break;
case SGValue::LONG:
_node->setLongValue(_assign_value->getLongValue());
break;
case SGValue::FLOAT:
_node->setFloatValue(_assign_value->getFloatValue());
break;
case SGValue::DOUBLE:
_node->setDoubleValue(_assign_value->getDoubleValue());
break;
case SGValue::STRING:
_node->setStringValue(_assign_value->getStringValue());
break;
case SGValue::UNKNOWN:
_node->setUnknownValue(_assign_value->getStringValue());
break;
}
break;
}
}
@ -225,7 +225,7 @@ FGBinding::fire () const
// Implementation of FGInput.
////////////////////////////////////////////////////////////////////////
// From main.cxx
// From main.cxx
extern void fgReshape( int width, int height );
FGInput current_input;
@ -233,102 +233,101 @@ FGInput current_input;
FGInput::FGInput ()
{
// no op
// no op
}
FGInput::~FGInput ()
{
// no op
// no op
}
void
FGInput::init ()
{
// Read the keyboard bindings.
// TODO: zero the old bindings first.
const SGPropertyNode * keyboard =
globals->get_props()->getNode("/input/keyboard", true);
vector<const SGPropertyNode *> keys = keyboard->getChildren("key");
// Read the keyboard bindings.
// TODO: zero the old bindings first.
const SGPropertyNode * keyboard =
globals->get_props()->getNode("/input/keyboard", true);
vector<const SGPropertyNode *> keys = keyboard->getChildren("key");
for (unsigned int i = 0; i < keys.size(); i++) {
int code = keys[i]->getIndex();
int modifiers = FG_MOD_NONE;
if (keys[i]->getBoolValue("mod-shift"))
modifiers |= FG_MOD_SHIFT;
if (keys[i]->getBoolValue("mod-ctrl"))
modifiers |= FG_MOD_CTRL;
if (keys[i]->getBoolValue("mod-alt"))
modifiers |= FG_MOD_ALT;
for (unsigned int i = 0; i < keys.size(); i++) {
int code = keys[i]->getIntValue("code", -1);
int modifiers = FG_MOD_NONE;
if (keys[i]->getBoolValue("mod-shift"))
modifiers |= FG_MOD_SHIFT;
if (keys[i]->getBoolValue("mod-ctrl"))
modifiers |= FG_MOD_CTRL;
if (keys[i]->getBoolValue("mod-alt"))
modifiers |= FG_MOD_ALT;
if (code < 0) {
SG_LOG(SG_INPUT, SG_ALERT, "Key stroke not bound = "
<< keys[i]->getStringValue("name", "[unnamed]"));
} else {
SG_LOG(SG_INPUT, SG_INFO, "Binding key " << code
<< " with modifiers " << modifiers);
vector<const SGPropertyNode *> bindings =
keys[i]->getChildren("binding");
for (unsigned int j = 0; j < bindings.size(); j++) {
SG_LOG(SG_INPUT, SG_INFO, " Adding binding " << j);
_key_bindings[modifiers][code].push_back(FGBinding(bindings[j]));
}
}
if (code < 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No code provided for key "
<< keys[i]->getStringValue("name", "[unnamed]"));
} else {
SG_LOG(SG_INPUT, SG_INFO, "Binding key " << code
<< " with modifiers " << modifiers);
vector<const SGPropertyNode *> bindings =
keys[i]->getChildren("binding");
for (unsigned int j = 0; j < bindings.size(); j++) {
SG_LOG(SG_INPUT, SG_INFO, " Adding binding " << j);
_key_bindings[modifiers][code].push_back(FGBinding(bindings[j]));
}
}
}
}
void
FGInput::bind ()
{
// no op
// no op
}
void
FGInput::unbind ()
{
// no op
// no op
}
void
FGInput::update ()
{
// we'll do something here with the joystick
// we'll do something here with the joystick
}
void
FGInput::doKey (int k, int modifiers, int x, int y)
{
float fov, tmp;
static bool winding_ccw = true;
int speed;
float fov, tmp;
static bool winding_ccw = true;
int speed;
SG_LOG(SG_INPUT, SG_INFO, "User pressed key " << k
<< " with modifiers " << modifiers);
SG_LOG(SG_INPUT, SG_INFO, "User pressed key " << k
<< " with modifiers " << modifiers);
if (_key_bindings[modifiers].find(k) != _key_bindings[modifiers].end()) {
const vector<FGBinding> &bindings = _key_bindings[modifiers][k];
for (unsigned int i = 0; i < bindings.size(); i++) {
bindings[i].fire();
}
return;
}
const vector<FGBinding> * bindings = _find_bindings(k, modifiers);
if (bindings != 0) {
for (unsigned int i = 0; i < bindings->size(); i++)
(*bindings)[i].fire();
return;
}
SG_LOG(SG_INPUT, SG_INFO, "(No user binding.)");
SG_LOG(SG_INPUT, SG_INFO, "(No user binding.)");
// Use the old, default actions.
FGInterface *f = current_aircraft.fdm_state;
FGViewer *v = globals->get_current_view();
// Use the old, default actions.
FGInterface *f = current_aircraft.fdm_state;
FGViewer *v = globals->get_current_view();
// everything after here will be removed sooner or later...
// everything after here will be removed sooner or later...
if (modifiers & FG_MOD_SHIFT) {
if (modifiers & FG_MOD_SHIFT) {
switch (k) {
case 7: // Ctrl-G key
current_autopilot->set_AltitudeMode(
FGAutopilot::FG_ALTITUDE_GS1 );
FGAutopilot::FG_ALTITUDE_GS1 );
current_autopilot->set_AltitudeEnabled(
! current_autopilot->get_AltitudeEnabled()
);
! current_autopilot->get_AltitudeEnabled()
);
return;
case 18: // Ctrl-R key
// temporary
@ -341,15 +340,15 @@ FGInput::doKey (int k, int modifiers, int x, int y)
return;
case 19: // Ctrl-S key
current_autopilot->set_AutoThrottleEnabled(
! current_autopilot->get_AutoThrottleEnabled()
);
! current_autopilot->get_AutoThrottleEnabled()
);
return;
case 20: // Ctrl-T key
current_autopilot->set_AltitudeMode(
FGAutopilot::FG_ALTITUDE_TERRAIN );
FGAutopilot::FG_ALTITUDE_TERRAIN );
current_autopilot->set_AltitudeEnabled(
! current_autopilot->get_AltitudeEnabled()
);
! current_autopilot->get_AltitudeEnabled()
);
return;
case 49: // numeric keypad 1
v->set_goal_view_offset( SGD_PI * 0.75 );
@ -420,7 +419,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
#endif
return;
// START SPECIALS
// START SPECIALS
case 256+GLUT_KEY_F1: {
ifstream input("fgfs.sav");
@ -456,6 +455,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
current_panel->unbind();
delete current_panel;
current_panel = new_panel;
current_panel->bind();
return;
}
case 256+GLUT_KEY_F4: {
@ -529,7 +529,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
v->set_goal_view_offset( SGD_PI * 1.75 );
return;
// END SPECIALS
// END SPECIALS
}
@ -632,7 +632,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
ConfirmExitDialog();
return;
// START SPECIALS
// START SPECIALS
case 256+GLUT_KEY_F2: // F2 Reload Tile Cache...
{
@ -644,8 +644,8 @@ FGInput::doKey (int k, int modifiers, int x, int y)
if ( global_tile_mgr.init() ) {
// Load the local scenery data
global_tile_mgr.update(
cur_fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES,
cur_fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES );
cur_fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES,
cur_fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES );
} else {
SG_LOG( SG_GENERAL, SG_ALERT,
"Error in Tile Manager initialization!" );
@ -653,7 +653,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
}
BusyCursor(1);
if ( !freeze )
globals->set_freeze( false );
globals->set_freeze( false );
return;
}
case 256+GLUT_KEY_F3: // F3 Take a screen shot
@ -666,28 +666,28 @@ FGInput::doKey (int k, int modifiers, int x, int y)
if ( current_autopilot->get_HeadingMode() !=
FGAutopilot::FG_HEADING_WAYPOINT ) {
current_autopilot->set_HeadingMode(
FGAutopilot::FG_HEADING_WAYPOINT );
FGAutopilot::FG_HEADING_WAYPOINT );
current_autopilot->set_HeadingEnabled( true );
} else {
current_autopilot->set_HeadingMode(
FGAutopilot::FG_TC_HEADING_LOCK );
FGAutopilot::FG_TC_HEADING_LOCK );
}
return;
case 256+GLUT_KEY_F8: {// F8 toggles fog ... off fastest nicest...
const string &fog = fgGetString("/sim/rendering/fog");
if (fog == "disabled") {
fgSetString("/sim/rendering/fog", "fastest");
SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=fastest");
fgSetString("/sim/rendering/fog", "fastest");
SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=fastest");
} else if (fog == "fastest") {
fgSetString("/sim/rendering/fog", "nicest");
SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=nicest");
fgSetString("/sim/rendering/fog", "nicest");
SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=nicest");
} else if (fog == "nicest") {
fgSetString("/sim/rendering/fog", "disabled");
SG_LOG(SG_INPUT, SG_INFO, "Fog disabled");
fgSetString("/sim/rendering/fog", "disabled");
SG_LOG(SG_INPUT, SG_INFO, "Fog disabled");
} else {
fgSetString("/sim/rendering/fog", "disabled");
SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
<< fog << ", changed to 'disabled'");
fgSetString("/sim/rendering/fog", "disabled");
SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
<< fog << ", changed to 'disabled'");
}
return;
}
@ -715,7 +715,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
return;
}
// END SPECIALS
// END SPECIALS
}
}
@ -724,112 +724,128 @@ FGInput::doKey (int k, int modifiers, int x, int y)
void
FGInput::action (const SGPropertyNode * binding)
{
const string &action = binding->getStringValue("action", "");
const string &control = binding->getStringValue("control", "");
bool repeatable = binding->getBoolValue("repeatable", false);
int step = binding->getIntValue("step", 0.0);
const string &action = binding->getStringValue("action", "");
const string &control = binding->getStringValue("control", "");
bool repeatable = binding->getBoolValue("repeatable", false);
int step = binding->getIntValue("step", 0.0);
if (control == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
<< binding->getIndex());
return;
}
if (control == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
<< binding->getIndex());
return;
}
else if (action == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
<< binding->getIndex());
return;
}
else if (action == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
<< binding->getIndex());
return;
}
else if (action == "switch") {
fgSetBool(control, !fgGetBool(control));
}
else if (action == "switch") {
fgSetBool(control, !fgGetBool(control));
}
else if (action == "adjust") {
const SGValue * step = binding->getValue("step");
if (step == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No step supplied for adjust action for key "
<< binding->getIndex());
return;
}
SGValue * target = fgGetValue(control, true);
// Use the target's type...
switch (target->getType()) {
case SGValue::BOOL:
case SGValue::INT:
target->setIntValue(target->getIntValue() + step->getIntValue());
break;
case SGValue::LONG:
target->setLongValue(target->getLongValue() + step->getLongValue());
break;
case SGValue::FLOAT:
target->setFloatValue(target->getFloatValue() + step->getFloatValue());
break;
case SGValue::DOUBLE:
case SGValue::UNKNOWN: // treat unknown as a double
target->setDoubleValue(target->getDoubleValue()
+ step->getDoubleValue());
break;
case SGValue::STRING:
SG_LOG(SG_INPUT, SG_ALERT, "Failed attempt to adjust string property "
<< control);
break;
}
else if (action == "adjust") {
const SGValue * step = binding->getValue("step");
if (step == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No step supplied for adjust action for key "
<< binding->getIndex());
return;
}
SGValue * target = fgGetValue(control, true);
// Use the target's type...
switch (target->getType()) {
case SGValue::BOOL:
case SGValue::INT:
target->setIntValue(target->getIntValue() + step->getIntValue());
break;
case SGValue::LONG:
target->setLongValue(target->getLongValue() + step->getLongValue());
break;
case SGValue::FLOAT:
target->setFloatValue(target->getFloatValue() + step->getFloatValue());
break;
case SGValue::DOUBLE:
case SGValue::UNKNOWN: // treat unknown as a double
target->setDoubleValue(target->getDoubleValue()
+ step->getDoubleValue());
break;
case SGValue::STRING:
SG_LOG(SG_INPUT, SG_ALERT, "Failed attempt to adjust string property "
<< control);
break;
}
}
else if (action == "assign") {
const SGValue * value = binding->getValue("value");
if (value == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No value supplied for assign action for key "
<< binding->getIndex());
return;
}
SGValue * target = fgGetValue(control, true);
// Use the target's type...
switch (target->getType()) {
case SGValue::BOOL:
target->setBoolValue(value->getBoolValue());
break;
case SGValue::INT:
target->setIntValue(value->getIntValue());
break;
case SGValue::LONG:
target->setLongValue(value->getLongValue());
break;
case SGValue::FLOAT:
target->setFloatValue(value->getFloatValue());
break;
case SGValue::DOUBLE:
target->setDoubleValue(value->getDoubleValue());
break;
case SGValue::STRING:
target->setStringValue(value->getStringValue());
break;
case SGValue::UNKNOWN:
target->setUnknownValue(value->getStringValue());
break;
}
else if (action == "assign") {
const SGValue * value = binding->getValue("value");
if (value == 0) {
SG_LOG(SG_INPUT, SG_ALERT, "No value supplied for assign action for key "
<< binding->getIndex());
return;
}
SGValue * target = fgGetValue(control, true);
// Use the target's type...
switch (target->getType()) {
case SGValue::BOOL:
target->setBoolValue(value->getBoolValue());
break;
case SGValue::INT:
target->setIntValue(value->getIntValue());
break;
case SGValue::LONG:
target->setLongValue(value->getLongValue());
break;
case SGValue::FLOAT:
target->setFloatValue(value->getFloatValue());
break;
case SGValue::DOUBLE:
target->setDoubleValue(value->getDoubleValue());
break;
case SGValue::STRING:
target->setStringValue(value->getStringValue());
break;
case SGValue::UNKNOWN:
target->setUnknownValue(value->getStringValue());
break;
}
}
else {
SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
<< " for key " << binding->getIndex());
}
else {
SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
<< " for key " << binding->getIndex());
}
}
#if 0
FGViewer *v = globals->get_current_view();
const vector<FGBinding> *
FGInput::_find_bindings (int k, int modifiers)
{
keyboard_map::const_iterator it = _key_bindings[modifiers].find(k);
SG_LOG( SG_INPUT, SG_DEBUG, "Special key hit = " << k );
// Try it straight, first.
if (it != _key_bindings[modifiers].end())
return &(_key_bindings[modifiers][k]);
if ( GLUT_ACTIVE_SHIFT && glutGetModifiers() ) {
SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
switch (k)
} else
}
// Try removing the control modifier
// for control keys.
else if ((modifiers&FG_MOD_CTRL) && iscntrl(k))
return _find_bindings(k, modifiers&~FG_MOD_CTRL);
#endif
// Try removing shift modifier
// for upper case or any punctuation
// (since different keyboards will
// shift different punctuation types)
else if ((modifiers&FG_MOD_SHIFT) && (isupper(k) || ispunct(k)))
return _find_bindings(k, modifiers&~FG_MOD_SHIFT);
// Try removing alt modifier for
// high-bit characters.
else if ((modifiers&FG_MOD_ALT) && k >= 128 && k < 256)
return _find_bindings(k, modifiers&~FG_MOD_ALT);
else
return 0;
}
// end of input.cxx