1 /**************************************************************************
4 * Written 1998 by Durk Talsma, started Juni, 1998. For the flight gear
7 * Additional mouse supported added by David Megginson, 1999.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 **************************************************************************/
31 #include <simgear/compiler.h>
33 #ifdef SG_MATH_EXCEPTION_CLASH
41 #include <Main/fg_os.hxx>
43 #if defined(FX) && defined(XMESA)
44 # include <GL/xmesa.h>
52 #include <simgear/constants.h>
53 #include <simgear/debug/logstream.hxx>
54 #include <simgear/misc/sg_path.hxx>
56 #include <Include/general.hxx>
57 #include <Aircraft/aircraft.hxx>
58 #include <Aircraft/controls.hxx>
59 #include <Airports/simple.hxx>
60 #include <Cockpit/panel.hxx>
61 #include <FDM/flight.hxx>
62 #include <Main/fg_init.hxx>
63 #include <Main/fg_props.hxx>
64 #include <Main/viewmgr.hxx>
67 #include "gui_local.hxx"
72 /* --------------------------------------------------------------------
74 ---------------------------------------------------------------------*/
78 static int _savedX = 0;
79 static int _savedY = 0;
80 static int last_buttons = 0 ;
81 static int mouse_active = 0;
82 static int mouse_joystick_control = 0;
84 //static time_t mouse_off_time;
85 //static int mouse_timed_out;
87 // to allow returning to previous view
88 // on second left click in MOUSE_VIEW mode
89 // This has file scope so that it can be reset
90 // if the little rodent is moved NHV
91 static int _mVtoggle = 0;
93 static int MOUSE_XSIZE = 0;
94 static int MOUSE_YSIZE = 0;
96 // uncomment this for view to exactly follow mouse in MOUSE_VIEW mode
97 // else smooth out the view panning to .01 radian per frame
98 // see view_offset smoothing mechanism in main.cxx
99 #define NO_SMOOTH_MOUSE_VIEW
101 // uncomment following to
102 #define RESET_VIEW_ON_LEAVING_MOUSE_VIEW
104 /* --------------------------------------------------------------------
105 Support for mouse as control yoke (david@megginson.com)
107 - right button toggles between pointer and yoke
108 - horizontal drag with no buttons moves ailerons
109 - vertical drag with no buttons moves elevators
110 - horizontal drag with left button moves brakes (left=on)
111 - vertical drag with left button moves throttle (up=more)
112 - horizontal drag with middle button moves rudder
113 - vertical drag with middle button moves trim
115 For the *_sensitivity variables, a lower number means more sensitive.
117 TODO: figure out how to keep pointer from leaving window in yoke mode.
118 TODO: add thresholds and null zones
119 TODO: sensitivity should be configurable at user option.
120 TODO: allow differential braking (this will be useful if FlightGear
121 ever supports tail-draggers like the DC-3)
122 ---------------------------------------------------------------------*/
124 MouseMode mouse_mode = MOUSE_POINTER;
126 static double aileron_sensitivity = 1.0/500.0;
127 static double elevator_sensitivity = 1.0/500.0;
128 static double brake_sensitivity = 1.0/250.0;
129 static double throttle_sensitivity = 1.0/250.0;
130 static double rudder_sensitivity = 1.0/500.0;
131 static double trim_sensitivity = 1.0/1000.0;
133 void guiInitMouse(int width, int height)
136 MOUSE_YSIZE = height;
139 static inline int guiGetMouseButton(void)
144 static inline void guiGetMouse(int *x, int *y)
150 static inline int left_button( void ) {
151 return( last_buttons & (1 << MOUSE_BUTTON_LEFT) );
154 static inline int middle_button( void ) {
155 return( last_buttons & (1 << MOUSE_BUTTON_MIDDLE) );
158 static inline int right_button( void ) {
159 return( last_buttons & (1 << MOUSE_BUTTON_RIGHT) );
162 static inline void set_goal_view_offset( float offset )
164 globals->get_current_view()->setGoalHeadingOffset_deg(offset * SGD_RADIANS_TO_DEGREES);
167 static inline void set_view_offset( float offset )
169 globals->get_current_view()->setHeadingOffset_deg(offset * SGD_RADIANS_TO_DEGREES);
172 static inline void set_goal_view_tilt( float tilt )
174 globals->get_current_view()->setGoalPitchOffset_deg(tilt);
177 static inline void set_view_tilt( float tilt )
179 globals->get_current_view()->setPitchOffset_deg(tilt);
182 static inline float get_view_offset() {
183 return globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS;
186 static inline float get_goal_view_offset() {
187 return globals->get_current_view()->getGoalHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS;
190 static inline void move_brake(float offset) {
191 globals->get_controls()->move_brake_left(offset);
192 globals->get_controls()->move_brake_right(offset);
195 static inline void move_throttle(float offset) {
196 globals->get_controls()->move_throttle(FGControls::ALL_ENGINES, offset);
199 static inline void move_rudder(float offset) {
200 globals->get_controls()->move_rudder(offset);
203 static inline void move_elevator_trim(float offset) {
204 globals->get_controls()->move_elevator_trim(offset);
207 static inline void move_aileron(float offset) {
208 globals->get_controls()->move_aileron(offset);
211 static inline void move_elevator(float offset) {
212 globals->get_controls()->move_elevator(offset);
215 static inline float get_aileron() {
216 return globals->get_controls()->get_aileron();
219 static inline float get_elevator() {
220 return globals->get_controls()->get_elevator();
223 static inline bool AP_HeadingEnabled() {
224 static const SGPropertyNode *heading_enabled
225 = fgGetNode("/autopilot/locks/heading");
226 return ( strcmp( heading_enabled->getStringValue(), "" ) != 0 );
229 static inline bool AP_AltitudeEnabled() {
230 static const SGPropertyNode *altitude_enabled
231 = fgGetNode("/autopilot/locks/altitude");
232 return ( strcmp( altitude_enabled->getStringValue(), "" ) != 0 );
235 void TurnCursorOn( void )
239 switch (mouse_mode) {
241 fgSetMouseCursor(MOUSE_CURSOR_POINTER);
244 fgSetMouseCursor(MOUSE_CURSOR_CROSSHAIR);
247 fgSetMouseCursor(MOUSE_CURSOR_LEFTRIGHT);
251 #if defined(X_CURSOR_TWEAKS)
252 fgWarpMouse( MOUSE_XSIZE/2, MOUSE_YSIZE/2 );
256 void TurnCursorOff( void )
259 #if defined(WIN32_CURSOR_TWEAKS)
260 fgSetMouseCursor(MOUSE_CURSOR_NONE);
261 #elif defined(X_CURSOR_TWEAKS)
262 fgWarpMouse( MOUSE_XSIZE, MOUSE_YSIZE );
266 void maybeToggleMouse( void )
268 #if defined(WIN32_CURSOR_TWEAKS_OFF)
269 static int first_time = ~0;
270 static int mouse_changed = 0;
274 mouse_changed = ~mouse_changed;
278 if( mouse_mode != MOUSE_POINTER )
280 if( mouse_changed ) {
281 mouse_changed = ~mouse_changed;
287 first_time = ~first_time;
288 #endif // #ifdef WIN32
291 //#define TRANSLATE_HUD
292 // temporary hack until pitch_offset is added to view pipeline
293 void fgTranslateHud( void ) {
295 if(mouse_mode == MOUSE_VIEW) {
297 int ww = MOUSE_XSIZE;
298 int wh = MOUSE_YSIZE;
300 float y = 4*(_mY-(wh/2));// * ((wh/SGD_PI)*SG_RADIANS_TO_DEGREES);
302 float x = get_view_offset() * SG_RADIANS_TO_DEGREES;
304 if( x < -180 ) x += 360;
305 else if( x > 180 ) x -= 360;
311 // glTranslatef( x*ww/640, y*wh/480, 0 );
312 glTranslatef( x*640/ww, y*480/wh, 0 );
314 #endif // TRANSLATE_HUD