1
0
Fork 0

I'm attaching diffs to add a new FGInput module to FlightGear

(src/Input).  So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.

The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance).  I have not managed to move all keybindings into this file
yet, but I've made a good start.  I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.

This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.

Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
This commit is contained in:
curt 2001-05-23 23:01:15 +00:00
parent 7208b95d36
commit 94f745e3ea
6 changed files with 74 additions and 772 deletions

View file

@ -75,6 +75,7 @@ fgfs_LDADD = \
$(top_builddir)/src/Objects/libObjects.a \
$(top_builddir)/src/Time/libTime.a \
$(WEATHER_LIBS) \
$(top_builddir)/src/Input/libInput.a \
$(top_builddir)/src/Joystick/libJoystick.a \
-lsgroute -lsgsky -lsgephem -lsgtiming -lsgio -lsgscreen \
-lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \

View file

@ -80,6 +80,7 @@
#include <FDM/LaRCsim.hxx>
#include <FDM/MagicCarpet.hxx>
#include <Include/general.hxx>
#include <Input/input.hxx>
#include <Joystick/joystick.hxx>
#include <Objects/matlib.hxx>
#include <Navaids/fixlist.hxx>
@ -754,6 +755,14 @@ bool fgInitSubsystems( void ) {
controls.bind();
////////////////////////////////////////////////////////////////////
// Initialize the input subsystem.
////////////////////////////////////////////////////////////////////
current_input.init();
current_input.bind();
////////////////////////////////////////////////////////////////////////
// End of subsystem initialization.
////////////////////////////////////////////////////////////////////

View file

@ -1,8 +1,8 @@
// fg_props.cxx -- support for
// fg_props.cxx -- support for FlightGear properties.
//
// Written by David Megginson, started November 1999.
// Written by David Megginson, started 2000.
//
// Copyright (C) 1999, 2000 David Megginson - david@megginson.com
// Copyright (C) 2000, 2001 David Megginson - david@megginson.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as

View file

@ -19,13 +19,28 @@ extern bool fgLoadFlight (istream &input);
// Convenience functions for getting property values.
////////////////////////////////////////////////////////////////////////
/**
* Get a property node.
*
* @param path The path of the node, relative to root.
* @param create true to create the node if it doesn't exist.
*/
inline SGPropertyNode *
fgGetNode (const string &path, bool create = false)
{
return globals->get_props()->getNode(path, create);
}
/**
* Get an SGValue pointer that can be queried repeatedly.
*
* If the property value is going to be accessed within the loop,
* it is best to use this method for maximum efficiency.
*/
inline SGValue * fgGetValue (const string &name, bool create = false)
inline SGValue *
fgGetValue (const string &name, bool create = false)
{
return globals->get_props()->getValue(name, create);
}

View file

@ -29,796 +29,72 @@
# include <windows.h>
#endif
#include <GL/glut.h>
#include <plib/pu.h>
#include <simgear/compiler.h>
#include <GL/glut.h>
#include <GL/gl.h>
#if defined(FX) && defined(XMESA)
#include <GL/xmesa.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include STL_FSTREAM
#include <plib/pu.h> // plib include
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Aircraft/aircraft.hxx>
#include <Autopilot/auto_gui.hxx>
#include <Autopilot/newauto.hxx>
#include <Cockpit/hud.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/panel_io.hxx>
#include <GUI/gui.h>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <Objects/matlib.hxx>
#include <Time/light.hxx>
#include <Time/tmp.hxx>
#ifndef FG_OLD_WEATHER
# include <WeatherCM/FGLocalWeatherDatabase.h>
#else
# include <Weather/weather.hxx>
#endif
#include "bfi.hxx"
#include "globals.hxx"
#include "keyboard.hxx"
#include "fg_props.hxx"
#include "options.hxx"
// From main.cxx
extern void fgReshape( int width, int height );
#ifdef BOOL
#error A sloppy coder has defined BOOL as a macro!
#undef BOOL
#endif
#include <Input/input.hxx>
/**
* Fire a user-defined key binding.
*
* <p>This function is temporary; eventually, all of the keyboard,
* joystick, and mouse support should migrate into a common Input
* module.</p>
*
* @param binding The property node for the binding.
* Construct the modifiers.
*/
static void
doBinding (const SGPropertyNode * binding)
static inline int get_mods ()
{
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);
int glut_modifiers = glutGetModifiers();
int modifiers = 0;
if (control == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
<< binding->getIndex());
return;
}
if (glut_modifiers & GLUT_ACTIVE_SHIFT)
modifiers |= FGInput::MOD_SHIFT;
if (glut_modifiers & GLUT_ACTIVE_CTRL)
modifiers |= FGInput::MOD_CTRL;
if (glut_modifiers & GLUT_ACTIVE_ALT)
modifiers |= FGInput::MOD_ALT;
else if (action == "") {
SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
<< binding->getIndex());
return;
}
else if (action == "switch") {
SG_LOG(SG_INPUT, SG_INFO, "Toggling value of " << control);
fgSetBool(control, !fgGetBool(control));
}
else if (action == "adjust") {
const SGValue * step = binding->getValue("value");
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 {
SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
<< " for key " << binding->getIndex());
}
return modifiers;
}
/**
* Keyboard event handler for Glut.
*
* <p>Pass the value on to the FGInput module unless PUI wants it.</p>
*
* @param k The integer value for the key pressed.
* @param x (unused)
* @param y (unused)
*/
void GLUTkey(unsigned char k, int x, int y) {
float fov, tmp;
static bool winding_ccw = true;
int speed;
// First, check for a user override.
const SGPropertyNode * binding = globals->get_props()
->getNode("/input/keyboard/", true)->getChild("key", int(k));
if (binding != 0) {
doBinding(binding);
return;
}
// Use the old, default actions.
FGInterface *f = current_aircraft.fdm_state;
FGViewer *v = globals->get_current_view();
SG_LOG( SG_INPUT, SG_DEBUG, "Key hit = " << k );
if ( puKeyboard(k, PU_DOWN) ) {
return;
}
if ( GLUT_ACTIVE_ALT && glutGetModifiers() ) {
SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
switch (k) {
case 1: // Ctrl-A key
current_autopilot->set_AltitudeMode(
FGAutopilot::FG_ALTITUDE_LOCK );
current_autopilot->set_AltitudeEnabled(
! current_autopilot->get_AltitudeEnabled()
);
return;
case 7: // Ctrl-G key
current_autopilot->set_AltitudeMode(
FGAutopilot::FG_ALTITUDE_GS1 );
current_autopilot->set_AltitudeEnabled(
! current_autopilot->get_AltitudeEnabled()
);
return;
case 8: // Ctrl-H key
current_autopilot->set_HeadingMode(
FGAutopilot::FG_TC_HEADING_LOCK );
current_autopilot->set_HeadingEnabled(
! current_autopilot->get_HeadingEnabled()
);
return;
case 14: // Ctrl-N key
current_autopilot->set_HeadingMode(
FGAutopilot::FG_HEADING_NAV1 );
current_autopilot->set_HeadingEnabled(
! current_autopilot->get_HeadingEnabled()
);
return;
case 18: // Ctrl-R key
// temporary
winding_ccw = !winding_ccw;
if ( winding_ccw ) {
glFrontFace ( GL_CCW );
} else {
glFrontFace ( GL_CW );
}
return;
case 19: // Ctrl-S key
current_autopilot->set_AutoThrottleEnabled(
! current_autopilot->get_AutoThrottleEnabled()
);
return;
case 20: // Ctrl-T key
current_autopilot->set_AltitudeMode(
FGAutopilot::FG_ALTITUDE_TERRAIN );
current_autopilot->set_AltitudeEnabled(
! current_autopilot->get_AltitudeEnabled()
);
return;
case 21: // Ctrl-U key
// add 1000' of emergency altitude. Possibly good for
// unflipping yourself :-)
{
double alt = cur_fdm_state->get_Altitude() + 1000;
fgFDMForceAltitude( fgGetString("/sim/flight-model"),
alt * SG_FEET_TO_METER );
}
return;
case 49: // numeric keypad 1
v->set_goal_view_offset( SGD_PI * 0.75 );
return;
case 50: // numeric keypad 2
v->set_goal_view_offset( SGD_PI );
return;
case 51: // numeric keypad 3
v->set_goal_view_offset( SGD_PI * 1.25 );
return;
case 52: // numeric keypad 4
v->set_goal_view_offset( SGD_PI * 0.50 );
return;
case 54: // numeric keypad 6
v->set_goal_view_offset( SGD_PI * 1.50 );
return;
case 55: // numeric keypad 7
v->set_goal_view_offset( SGD_PI * 0.25 );
return;
case 56: // numeric keypad 8
v->set_goal_view_offset( 0.00 );
return;
case 57: // numeric keypad 9
v->set_goal_view_offset( SGD_PI * 1.75 );
return;
case 65: // A key
speed = fgGetInt("/sim/speed-up");
speed--;
if ( speed < 1 ) {
speed = 1;
}
fgSetInt("/sim/speed-up", speed);
return;
case 72: // H key
HUD_brightkey( true );
return;
case 73: // I key
// Minimal Hud
fgHUDInit2(&current_aircraft);
return;
case 77: // M key
globals->inc_warp( -60 );
fgUpdateSkyAndLightingParams();
return;
case 80: // P key
if (fgGetBool("/sim/panel/visibility"))
fgSetBool("/sim/panel/visibility", false);
else
fgSetBool("/sim/panel/visibility", true);
fgReshape(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
break;
case 84: // T key
globals->inc_warp_delta( -30 );
fgUpdateSkyAndLightingParams();
return;
case 87: // W key
#if defined(FX) && !defined(WIN32)
global_fullscreen = ( !global_fullscreen );
# if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
XMesaSetFXmode( global_fullscreen ?
XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
# endif
#endif
return;
case 88: // X key
fov = globals->get_current_view()->get_fov();
fov *= 1.05;
if ( fov > FG_FOV_MAX ) {
fov = FG_FOV_MAX;
}
globals->get_current_view()->set_fov(fov);
// v->force_update_fov_math();
return;
case 90: // Z key
#ifndef FG_OLD_WEATHER
tmp = WeatherDatabase->getWeatherVisibility();
tmp /= 1.10;
WeatherDatabase->setWeatherVisibility( tmp );
#else
tmp = current_weather.get_visibility(); // in meters
tmp /= 1.10;
current_weather.set_visibility( tmp );
#endif
return;
}
} else {
SG_LOG( SG_INPUT, SG_DEBUG, "" );
switch (k) {
case 50: // numeric keypad 2
if ( current_autopilot->get_AltitudeEnabled() ) {
current_autopilot->AltitudeAdjust( 100 );
} else {
controls.move_elevator(-0.05);
}
return;
case 56: // numeric keypad 8
if ( current_autopilot->get_AltitudeEnabled() ) {
current_autopilot->AltitudeAdjust( -100 );
} else {
controls.move_elevator(0.05);
}
return;
case 49: // numeric keypad 1
controls.move_elevator_trim(-0.001);
return;
case 55: // numeric keypad 7
controls.move_elevator_trim(0.001);
return;
case 52: // numeric keypad 4
controls.move_aileron(-0.05);
return;
case 54: // numeric keypad 6
controls.move_aileron(0.05);
return;
case 48: // numeric keypad Ins
if ( current_autopilot->get_HeadingEnabled() ) {
current_autopilot->HeadingAdjust( -1 );
} else {
controls.move_rudder(-0.05);
}
return;
case 13: // numeric keypad Enter
if ( current_autopilot->get_HeadingEnabled() ) {
current_autopilot->HeadingAdjust( 1 );
} else {
controls.move_rudder(0.05);
}
return;
case 53: // numeric keypad 5
controls.set_aileron(0.0);
controls.set_elevator(0.0);
controls.set_rudder(0.0);
return;
case 57: // numeric keypad 9 (Pg Up)
if ( current_autopilot->get_AutoThrottleEnabled() ) {
current_autopilot->AutoThrottleAdjust( 5 );
} else {
controls.move_throttle( FGControls::ALL_ENGINES, 0.01 );
}
return;
case 51: // numeric keypad 3 (Pg Dn)
if ( current_autopilot->get_AutoThrottleEnabled() ) {
current_autopilot->AutoThrottleAdjust( -5 );
} else {
controls.move_throttle( FGControls::ALL_ENGINES, -0.01 );
}
return;
case 91: // [ key
controls.move_flaps(-0.34);
SG_LOG( SG_INPUT, SG_INFO,
"Set flaps to " << controls.get_flaps() );
return;
case 93: // ] key
controls.move_flaps(0.34);
SG_LOG( SG_INPUT, SG_INFO,
"Set flaps to " << controls.get_flaps() );
return;
case 97: // a key
speed = fgGetInt("/sim/speed-up");
speed++;
fgSetInt("/sim/speed-up", speed);
return;
case 98: // b key
int b_ret;
double b_set;
b_ret = int( controls.get_brake( 0 ) );
b_set = double(!b_ret);
controls.set_brake( FGControls::ALL_WHEELS, b_set);
return;
case 44: // , key
if (controls.get_brake(0) > 0.0) {
controls.set_brake(0, 0.0);
} else {
controls.set_brake(0, 1.0);
}
return;
case 46: // . key
if (controls.get_brake(1) > 0.0) {
controls.set_brake(1, 0.0);
} else {
controls.set_brake(1, 1.0);
}
return;
case 104: // h key
HUD_masterswitch( true );
return;
case 105: // i key
fgHUDInit(&current_aircraft); // normal HUD
return;
case 109: // m key
globals->inc_warp( 60 );
fgUpdateSkyAndLightingParams();
return;
case 112: // p key
globals->set_freeze( ! globals->get_freeze() );
{
SGBucket p( f->get_Longitude() * SGD_RADIANS_TO_DEGREES,
f->get_Latitude() * SGD_RADIANS_TO_DEGREES );
SGPath tile_path( globals->get_fg_root() );
tile_path.append( "Scenery" );
tile_path.append( p.gen_base_path() );
tile_path.append( p.gen_index_str() );
// printf position and attitude information
printf( "Lon = %.6f Lat = %.6f Ground = %.2f Alt = %.2f\n",
f->get_Longitude() * SGD_RADIANS_TO_DEGREES,
f->get_Latitude() * SGD_RADIANS_TO_DEGREES,
scenery.cur_elev,
f->get_Altitude() * SG_FEET_TO_METER );
printf( "Heading = %.2f Roll = %.2f Pitch = %.2f\n",
f->get_Psi() * SGD_RADIANS_TO_DEGREES,
f->get_Phi() * SGD_RADIANS_TO_DEGREES,
f->get_Theta() * SGD_RADIANS_TO_DEGREES );
#if 0
SG_LOG( SG_INPUT, SG_INFO,
"Lon = " << f->get_Longitude() * SGD_RADIANS_TO_DEGREES
<< " Lat = " << f->get_Latitude() * SGD_RADIANS_TO_DEGREES
<< " Altitude = " << f->get_Altitude() * SG_FEET_TO_METER
);
SG_LOG( SG_INPUT, SG_INFO,
"Heading = " << f->get_Psi() * SGD_RADIANS_TO_DEGREES
<< " Roll = " << f->get_Phi() * SGD_RADIANS_TO_DEGREES
<< " Pitch = " << f->get_Theta() * SGD_RADIANS_TO_DEGREES );
#endif
SG_LOG( SG_INPUT, SG_INFO, tile_path.c_str());
}
return;
case 116: // t key
globals->inc_warp_delta( 30 );
fgUpdateSkyAndLightingParams();
return;
case 118: // v key
// handles GUI state as well as Viewer LookAt Direction
CenterView();
globals->set_current_view( globals->get_viewmgr()->next_view() );
fgReshape( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
return;
case 120: // x key
fov = globals->get_current_view()->get_fov();
fov /= 1.05;
if ( fov < FG_FOV_MIN ) {
fov = FG_FOV_MIN;
}
globals->get_current_view()->set_fov(fov);
// v->force_update_fov_math();
return;
case 122: // z key
#ifndef FG_OLD_WEATHER
tmp = WeatherDatabase->getWeatherVisibility();
tmp *= 1.10;
WeatherDatabase->setWeatherVisibility( tmp );
#else
tmp = current_weather.get_visibility(); // in meters
tmp *= 1.10;
current_weather.set_visibility( tmp );
#endif
return;
case 27: // ESC
// if( fg_DebugOutput ) {
// fclose( fg_DebugOutput );
// }
SG_LOG( SG_INPUT, SG_ALERT,
"Program exit requested." );
ConfirmExitDialog();
return;
}
}
void GLUTkey(unsigned char k, int x, int y)
{
// Give PUI a chance to grab it first.
if (!puKeyboard(k, PU_DOWN))
// This is problematic; it allows
// (say) P and [SHIFT]P to be
// distinguished, but is that a good
// idea?
current_input.doKey(k, get_mods(), x, y);
}
// Handle "special" keyboard events
void GLUTspecialkey(int k, int x, int y) {
FGViewer *v = globals->get_current_view();
SG_LOG( SG_INPUT, SG_DEBUG, "Special key hit = " << k );
if ( puKeyboard(k + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN) ) {
return;
}
if ( GLUT_ACTIVE_SHIFT && glutGetModifiers() ) {
SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
switch (k) {
case GLUT_KEY_F1: {
ifstream input("fgfs.sav");
if (input.good() && fgLoadFlight(input)) {
input.close();
SG_LOG(SG_INPUT, SG_INFO, "Restored flight from fgfs.sav");
} else {
SG_LOG(SG_INPUT, SG_ALERT, "Cannot load flight from fgfs.sav");
}
return;
}
case GLUT_KEY_F2: {
SG_LOG(SG_INPUT, SG_INFO, "Saving flight");
cerr << "Opening output stream" << endl;
ofstream output("fgfs.sav");
cerr << "output stream opened" << endl;
if (output.good() && fgSaveFlight(output)) {
output.close();
SG_LOG(SG_INPUT, SG_INFO, "Saved flight to fgfs.sav");
} else {
SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to fgfs.sav");
}
return;
}
case GLUT_KEY_F3: {
string panel_path =
fgGetString("/sim/panel/path", "Panels/Default/default.xml");
FGPanel * new_panel = fgReadPanel(panel_path);
if (new_panel == 0) {
SG_LOG(SG_INPUT, SG_ALERT,
"Error reading new panel from " << panel_path);
return;
}
SG_LOG(SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path);
current_panel->unbind();
delete current_panel;
current_panel = new_panel;
return;
}
case GLUT_KEY_F4: {
SGPath props_path(globals->get_fg_root());
props_path.append("preferences.xml");
SG_LOG(SG_INPUT, SG_INFO, "Rereading global preferences");
if (!readProperties(props_path.str(), globals->get_props())) {
SG_LOG(SG_INPUT, SG_ALERT,
"Failed to reread global preferences from "
<< props_path.str());
} else {
SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
}
return;
}
case GLUT_KEY_F5: {
current_panel->setYOffset(current_panel->getYOffset() - 5);
fgReshape(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
return;
}
case GLUT_KEY_F6: {
current_panel->setYOffset(current_panel->getYOffset() + 5);
fgReshape(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
return;
}
case GLUT_KEY_F7: {
current_panel->setXOffset(current_panel->getXOffset() - 5);
return;
}
case GLUT_KEY_F8: {
current_panel->setXOffset(current_panel->getXOffset() + 5);
return;
}
// case GLUT_KEY_F9: {
// return;
// }
case GLUT_KEY_F10: {
fgToggleFDMdataLogging();
return;
}
// case GLUT_KEY_F11: {
// return;
// }
// case GLUT_KEY_F12: {
// return;
// }
case GLUT_KEY_END: // numeric keypad 1
v->set_goal_view_offset( SGD_PI * 0.75 );
return;
case GLUT_KEY_DOWN: // numeric keypad 2
v->set_goal_view_offset( SGD_PI );
return;
case GLUT_KEY_PAGE_DOWN: // numeric keypad 3
v->set_goal_view_offset( SGD_PI * 1.25 );
return;
case GLUT_KEY_LEFT: // numeric keypad 4
v->set_goal_view_offset( SGD_PI * 0.50 );
return;
case GLUT_KEY_RIGHT: // numeric keypad 6
v->set_goal_view_offset( SGD_PI * 1.50 );
return;
case GLUT_KEY_HOME: // numeric keypad 7
v->set_goal_view_offset( SGD_PI * 0.25 );
return;
case GLUT_KEY_UP: // numeric keypad 8
v->set_goal_view_offset( 0.00 );
return;
case GLUT_KEY_PAGE_UP: // numeric keypad 9
v->set_goal_view_offset( SGD_PI * 1.75 );
return;
}
} else {
SG_LOG( SG_INPUT, SG_DEBUG, "" );
switch (k) {
case GLUT_KEY_F2: // F2 Reload Tile Cache...
{
bool freeze = globals->get_freeze();
SG_LOG(SG_INPUT, SG_INFO, "ReIniting TileCache");
if ( !freeze )
globals->set_freeze( true );
BusyCursor(0);
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 );
} else {
SG_LOG( SG_GENERAL, SG_ALERT,
"Error in Tile Manager initialization!" );
exit(-1);
}
BusyCursor(1);
if ( !freeze )
globals->set_freeze( false );
return;
}
case GLUT_KEY_F3: // F3 Take a screen shot
fgDumpSnapShot();
return;
case GLUT_KEY_F4: // F4 Update lighting manually
fgUpdateSkyAndLightingParams();
return;
case GLUT_KEY_F6: // F6 toggles Autopilot target location
if ( current_autopilot->get_HeadingMode() !=
FGAutopilot::FG_HEADING_WAYPOINT ) {
current_autopilot->set_HeadingMode(
FGAutopilot::FG_HEADING_WAYPOINT );
current_autopilot->set_HeadingEnabled( true );
} else {
current_autopilot->set_HeadingMode(
FGAutopilot::FG_TC_HEADING_LOCK );
}
return;
case 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");
} else if (fog == "fastest") {
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");
} else {
fgSetString("/sim/rendering/fog", "disabled");
SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
<< fog << ", changed to 'disabled'");
}
return;
}
case GLUT_KEY_F9: // F9 toggles textures on and off...
SG_LOG( SG_INPUT, SG_INFO, "Toggling texture" );
if ( fgGetBool("/sim/rendering/textures")) {
fgSetBool("/sim/rendering/textures", false);
material_lib.set_step( 1 );
} else {
fgSetBool("/sim/rendering/textures", true);
material_lib.set_step( 0 );
}
return;
case GLUT_KEY_F10: // F10 toggles menu on and off...
SG_LOG(SG_INPUT, SG_INFO, "Invoking call back function");
guiToggleMenu();
return;
case GLUT_KEY_F11: // F11 Altitude Dialog.
SG_LOG(SG_INPUT, SG_INFO, "Invoking Altitude call back function");
NewAltitude( NULL );
return;
case GLUT_KEY_F12: // F12 Heading Dialog...
SG_LOG(SG_INPUT, SG_INFO, "Invoking Heading call back function");
NewHeading( NULL );
return;
case GLUT_KEY_UP:
if ( current_autopilot->get_AltitudeEnabled() ) {
current_autopilot->AltitudeAdjust( -100 );
} else {
controls.move_elevator(0.05);
}
return;
case GLUT_KEY_DOWN:
if ( current_autopilot->get_AltitudeEnabled() ) {
current_autopilot->AltitudeAdjust( 100 );
} else {
controls.move_elevator(-0.05);
}
return;
case GLUT_KEY_LEFT:
controls.move_aileron(-0.05);
return;
case GLUT_KEY_RIGHT:
controls.move_aileron(0.05);
return;
case GLUT_KEY_HOME: // numeric keypad 1
controls.move_elevator_trim(0.001);
return;
case GLUT_KEY_END: // numeric keypad 7
controls.move_elevator_trim(-0.001);
return;
case GLUT_KEY_INSERT: // numeric keypad Ins
if ( current_autopilot->get_HeadingEnabled() ) {
current_autopilot->HeadingAdjust( -1 );
} else {
controls.move_rudder(-0.05);
}
return;
case 13: // numeric keypad Enter
if ( current_autopilot->get_HeadingEnabled() ) {
current_autopilot->HeadingAdjust( 1 );
} else {
controls.move_rudder(0.05);
}
return;
case 53: // numeric keypad 5
controls.set_aileron(0.0);
controls.set_elevator(0.0);
controls.set_rudder(0.0);
return;
case GLUT_KEY_PAGE_UP: // numeric keypad 9 (Pg Up)
if ( current_autopilot->get_AutoThrottleEnabled() ) {
current_autopilot->AutoThrottleAdjust( 5 );
} else {
controls.move_throttle( FGControls::ALL_ENGINES, 0.01 );
}
return;
case GLUT_KEY_PAGE_DOWN: // numeric keypad 3 (Pg Dn)
if ( current_autopilot->get_AutoThrottleEnabled() ) {
current_autopilot->AutoThrottleAdjust( -5 );
} else {
controls.move_throttle( FGControls::ALL_ENGINES, -0.01 );
}
return;
}
}
/**
* Special key handler for Glut.
*
* <p>Pass the value on to the FGInput module unless PUI wants it.
* The key value will have 256 added to it.</p>
*
* @param k The integer value for the key pressed (will have 256 added
* to it).
* @param x (unused)
* @param y (unused)
*/
void GLUTspecialkey(int k, int x, int y)
{
// Give PUI a chance to grab it first.
if (!puKeyboard(k + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN))
current_input.doKey(k + 256, get_mods(), x, y);
}
// end of keyboard.cxx

View file

@ -19,6 +19,7 @@ SUBDIRS = \
Controls \
FDM \
GUI \
Input \
Joystick \
Navaids \
$(NETWORK_DIRS) \