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:
parent
7208b95d36
commit
94f745e3ea
6 changed files with 74 additions and 772 deletions
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(¤t_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(¤t_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
|
||||
|
|
|
@ -19,6 +19,7 @@ SUBDIRS = \
|
|||
Controls \
|
||||
FDM \
|
||||
GUI \
|
||||
Input \
|
||||
Joystick \
|
||||
Navaids \
|
||||
$(NETWORK_DIRS) \
|
||||
|
|
Loading…
Reference in a new issue