]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
56bd8ed5436f78ae0afeb711288a9e20ae8b15b6
[flightgear.git] / src / Main / viewmgr.cxx
1 // viewmgr.cxx -- class for managing all the views in the flightgear world.
2 //
3 // Written by Curtis Olson, started October 2000.
4 //   partially rewritten by Jim Wilson March 2002
5 //
6 // Copyright (C) 2000  Curtis L. Olson  - curt@flightgear.org
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 //
22 // $Id$
23
24 #include <string.h>             // strcmp
25
26 #include <plib/sg.h>
27
28 #include <GUI/sgVec3Slider.hxx> // FIXME: this should NOT be needed
29
30 #include "viewmgr.hxx"
31 #include "fg_props.hxx"
32
33 // strings 
34 string viewpath, nodepath, strdata;
35
36 // Constructor
37 FGViewMgr::FGViewMgr( void ) :
38   axis_long(0),
39   axis_lat(0),
40   current(0)
41 {
42 }
43
44
45 // Destructor
46 FGViewMgr::~FGViewMgr( void ) {
47 }
48
49 void
50 FGViewMgr::init ()
51 {
52   char stridx [ 20 ];
53   bool from_model = false;
54   bool at_model = false;
55   int from_model_index = 0;
56   int at_model_index = 0;
57   double x_offset_m, y_offset_m, z_offset_m;
58   double near_m;
59
60   for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
61     viewpath = "/sim/view";
62     sprintf(stridx, "[%d]", i);
63     viewpath += stridx;
64
65     // find out what type of view this is...
66     nodepath = viewpath;
67     nodepath += "/type";
68     strdata = fgGetString(nodepath.c_str());
69
70     // FIXME:
71     // this is assumed to be an aircraft model...we will need to read
72     // model-from-type as well.
73     // find out if this is a model we are looking from...
74     nodepath = viewpath;
75     nodepath += "/config/from-model";
76     from_model = fgGetBool(nodepath.c_str());
77
78     // get model index (which model)
79     if (from_model) {
80       nodepath = viewpath;
81       nodepath += "/config/from-model-idx";
82       from_model_index = fgGetInt(nodepath.c_str());     
83     }
84
85     if ( strcmp("lookat",strdata.c_str()) == 0 ) {
86       // find out if this is a model we are looking at...
87       nodepath = viewpath;
88       nodepath += "/config/at-model";
89       at_model = fgGetBool(nodepath.c_str());
90
91       // get model index (which model)
92       if (at_model) {
93         nodepath = viewpath;
94         nodepath += "/config/at-model-idx";
95         at_model_index = fgGetInt(nodepath.c_str());     
96       }
97     }
98
99     nodepath = viewpath;
100     nodepath += "/config/x-offset-m";
101     x_offset_m = fgGetDouble(nodepath.c_str());
102     nodepath = viewpath;
103     nodepath += "/config/y-offset-m";
104     y_offset_m = fgGetDouble(nodepath.c_str());
105     nodepath = viewpath;
106     nodepath += "/config/z-offset-m";
107     z_offset_m = fgGetDouble(nodepath.c_str());
108
109     nodepath = viewpath;
110     nodepath += "/config/ground-level-nearplane-m";
111     near_m = fgGetDouble(nodepath.c_str());
112
113     // supporting two types now "lookat" = 1 and "lookfrom" = 0
114     if ( strcmp("lookat",strdata.c_str()) == 0 )
115       add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index,
116                               at_model, at_model_index, x_offset_m, y_offset_m,
117                               z_offset_m, near_m ));
118     else
119       add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index, false,
120                               0, x_offset_m, y_offset_m, z_offset_m, near_m ));
121
122   }
123
124   copyToCurrent();
125   
126 }
127
128 typedef double (FGViewMgr::*double_getter)() const;
129
130 void
131 FGViewMgr::bind ()
132 {
133   // these are bound to the current view properties
134   fgTie("/sim/current-view/heading-offset-deg", this,
135         &FGViewMgr::getViewOffset_deg, &FGViewMgr::setViewOffset_deg);
136   fgSetArchivable("/sim/current-view/heading-offset-deg");
137   fgTie("/sim/current-view/goal-heading-offset-deg", this,
138         &FGViewMgr::getGoalViewOffset_deg, &FGViewMgr::setGoalViewOffset_deg);
139   fgSetArchivable("/sim/current-view/goal-heading-offset-deg");
140   fgTie("/sim/current-view/pitch-offset-deg", this,
141         &FGViewMgr::getViewTilt_deg, &FGViewMgr::setViewTilt_deg);
142   fgSetArchivable("/sim/current-view/pitch-offset-deg");
143   fgTie("/sim/current-view/goal-pitch-offset-deg", this,
144         &FGViewMgr::getGoalViewTilt_deg, &FGViewMgr::setGoalViewTilt_deg);
145   fgSetArchivable("/sim/current-view/goal-pitch-offset-deg");
146
147   fgTie("/sim/current-view/axes/long", this,
148         (double_getter)0, &FGViewMgr::setViewAxisLong);
149   fgTie("/sim/current-view/axes/lat", this,
150         (double_getter)0, &FGViewMgr::setViewAxisLat);
151
152   fgTie("/sim/current-view/field-of-view", this,
153         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
154   fgSetArchivable("/sim/current-view/field-of-view");
155
156   fgTie("/sim/current-view/ground-level-nearplane-m", this,
157         &FGViewMgr::getNear_m, &FGViewMgr::setNear_m);
158   fgSetArchivable("/sim/current-view/ground-level-nearplane-m");
159
160 }
161
162 void
163 FGViewMgr::unbind ()
164 {
165   // FIXME:
166   // need to redo these bindings to the new locations (move to viewer?)
167   fgUntie("/sim/current-view/heading-offset-deg");
168   fgUntie("/sim/current-view/goal-heading-offset-deg");
169   fgUntie("/sim/current-view/pitch-offset-deg");
170   fgUntie("/sim/current-view/goal-pitch-offset-deg");
171   fgUntie("/sim/field-of-view");
172   fgUntie("/sim/current-view/axes/long");
173   fgUntie("/sim/current-view/axes/lat");
174 }
175
176 void
177 FGViewMgr::update (int dt)
178 {
179   char stridx [20];
180   double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
181
182   FGViewer * view = get_current_view();
183   if (view == 0)
184     return;
185
186   // 
187   int i = current;
188   viewpath = "/sim/view";
189   sprintf(stridx, "[%d]", i);
190   viewpath += stridx;
191
192
193   FGViewer *loop_view = (FGViewer *)get_view( i );
194
195                 // Set up view location and orientation
196
197   nodepath = viewpath;
198   nodepath += "/config/from-model";
199   if (!fgGetBool(nodepath.c_str())) {
200     nodepath = viewpath;
201     nodepath += "/config/eye-lon-deg-path";
202     lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
203     nodepath = viewpath;
204     nodepath += "/config/eye-lat-deg-path";
205     lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
206     nodepath = viewpath;
207     nodepath += "/config/eye-alt-ft-path";
208     alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
209     nodepath = viewpath;
210     nodepath += "/config/eye-roll-deg-path";
211     roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
212     nodepath = viewpath;
213     nodepath += "/config/eye-pitch-deg-path";
214     pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
215     nodepath = viewpath;
216     nodepath += "/config/eye-heading-deg-path";
217     heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
218     loop_view->setPosition(lon_deg, lat_deg, alt_ft);
219     loop_view->setOrientation(roll_deg, pitch_deg, heading_deg);
220   } else {
221     // force recalc in viewer
222     loop_view->set_dirty();
223   }
224
225   // if lookat (type 1) then get target data...
226   if (loop_view->getType() == 1) {
227     nodepath = viewpath;
228     nodepath += "/config/from-model";
229     if (!fgGetBool(nodepath.c_str())) {
230       nodepath = viewpath;
231       nodepath += "/config/target-lon-deg-path";
232       lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
233       nodepath = viewpath;
234       nodepath += "/config/target-lat-deg-path";
235       lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
236       nodepath = viewpath;
237       nodepath += "/config/target-alt-ft-path";
238       alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
239       nodepath = viewpath;
240       nodepath += "/config/target-roll-deg-path";
241       roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
242       nodepath = viewpath;
243       nodepath += "/config/target-pitch-deg-path";
244       pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
245       nodepath = viewpath;
246       nodepath += "/config/target-heading-deg-path";
247       heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
248      
249       loop_view ->setTargetPosition(lon_deg, lat_deg, alt_ft);
250       loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg);
251     } else {
252       loop_view->set_dirty();
253     }
254   }
255   setPilotXOffset_m(fgGetDouble("/sim/current-view/x-offset-m"));
256   setPilotYOffset_m(fgGetDouble("/sim/current-view/y-offset-m"));
257   setPilotZOffset_m(fgGetDouble("/sim/current-view/z-offset-m"));
258
259                                 // Update the current view
260   do_axes();
261   view->update(dt);
262   double tmp;
263 }
264
265 void
266 FGViewMgr::copyToCurrent()
267 {
268     fgSetDouble("/sim/current-view/x-offset-m", getPilotXOffset_m());
269     fgSetDouble("/sim/current-view/y-offset-m", getPilotYOffset_m());
270     fgSetDouble("/sim/current-view/z-offset-m", getPilotZOffset_m());
271 }
272
273
274 double
275 FGViewMgr::getViewOffset_deg () const
276 {
277   const FGViewer * view = get_current_view();
278   return (view == 0 ? 0 : view->getHeadingOffset_deg());
279 }
280
281 void
282 FGViewMgr::setViewOffset_deg (double offset)
283 {
284   FGViewer * view = get_current_view();
285   if (view != 0) {
286     view->setGoalHeadingOffset_deg(offset);
287     view->setHeadingOffset_deg(offset);
288   }
289 }
290
291 double
292 FGViewMgr::getGoalViewOffset_deg () const
293 {
294   const FGViewer * view = get_current_view();
295   return (view == 0 ? 0 : view->getGoalHeadingOffset_deg());
296 }
297
298 void
299 FGViewMgr::setGoalViewOffset_deg (double offset)
300 {
301   FGViewer * view = get_current_view();
302   if (view != 0)
303     view->setGoalHeadingOffset_deg(offset);
304 }
305
306 double
307 FGViewMgr::getViewTilt_deg () const
308 {
309   const FGViewer * view = get_current_view();
310   return (view == 0 ? 0 : view->getPitchOffset_deg());
311 }
312
313 void
314 FGViewMgr::setViewTilt_deg (double tilt)
315 {
316   FGViewer * view = get_current_view();
317   if (view != 0) {
318     view->setGoalPitchOffset_deg(tilt);
319     view->setPitchOffset_deg(tilt);
320   }
321 }
322
323 double
324 FGViewMgr::getGoalViewTilt_deg () const
325 {
326   const FGViewer * view = get_current_view();
327   return (view == 0 ? 0 : view->getGoalPitchOffset_deg());
328 }
329
330 void
331 FGViewMgr::setGoalViewTilt_deg (double tilt)
332 {
333   FGViewer * view = get_current_view();
334   if (view != 0)
335     view->setGoalPitchOffset_deg(tilt);
336 }
337
338 double
339 FGViewMgr::getPilotXOffset_m () const
340 {
341   const FGViewer * view = get_current_view();
342   if (view != 0) {
343     return ((FGViewer *)view)->getXOffset_m();
344   } else {
345     return 0;
346   }
347 }
348
349 void
350 FGViewMgr::setPilotXOffset_m (double x)
351 {
352   FGViewer * view = get_current_view();
353   if (view != 0) {
354     view->setXOffset_m(x);
355   }
356 }
357
358 double
359 FGViewMgr::getPilotYOffset_m () const
360 {
361   const FGViewer * view = get_current_view();
362   if (view != 0) {
363     return ((FGViewer *)view)->getYOffset_m();
364   } else {
365     return 0;
366   }
367 }
368
369 void
370 FGViewMgr::setPilotYOffset_m (double y)
371 {
372   FGViewer * view = get_current_view();
373   if (view != 0) {
374     view->setYOffset_m(y);
375   }
376 }
377
378 double
379 FGViewMgr::getPilotZOffset_m () const
380 {
381   const FGViewer * view = get_current_view();
382   if (view != 0) {
383     return ((FGViewer *)view)->getZOffset_m();
384   } else {
385     return 0;
386   }
387 }
388
389 void
390 FGViewMgr::setPilotZOffset_m (double z)
391 {
392   FGViewer * view = get_current_view();
393   if (view != 0) {
394     view->setZOffset_m(z);
395   }
396 }
397
398 double
399 FGViewMgr::getFOV_deg () const
400 {
401   const FGViewer * view = get_current_view();
402   return (view == 0 ? 0 : view->get_fov());
403 }
404
405 void
406 FGViewMgr::setFOV_deg (double fov)
407 {
408   FGViewer * view = get_current_view();
409   if (view != 0)
410     view->set_fov(fov);
411 }
412
413 double
414 FGViewMgr::getNear_m () const
415 {
416   const FGViewer * view = get_current_view();
417   return (view == 0 ? 0.5f : view->getNear_m());
418 }
419
420 void
421 FGViewMgr::setNear_m (double near_m)
422 {
423   FGViewer * view = get_current_view();
424   if (view != 0)
425     view->setNear_m(near_m);
426 }
427
428 void
429 FGViewMgr::setViewAxisLong (double axis)
430 {
431   axis_long = axis;
432 }
433
434 void
435 FGViewMgr::setViewAxisLat (double axis)
436 {
437   axis_lat = axis;
438 }
439
440 void
441 FGViewMgr::do_axes ()
442 {
443                                 // Take no action when hat is centered
444   if ( ( axis_long <  0.01 ) &&
445        ( axis_long > -0.01 ) &&
446        ( axis_lat  <  0.01 ) &&
447        ( axis_lat  > -0.01 )
448      )
449     return;
450
451   double viewDir = 999;
452
453   /* Do all the quick and easy cases */
454   if (axis_long < 0) {          // Longitudinal axis forward
455     if (axis_lat == axis_long)
456       viewDir = 45;
457     else if (axis_lat == - axis_long)
458       viewDir = 315;
459     else if (axis_lat == 0)
460       viewDir = 0;
461   } else if (axis_long > 0) {   // Longitudinal axis backward
462     if (axis_lat == - axis_long)
463       viewDir = 135;
464     else if (axis_lat == axis_long)
465       viewDir = 225;
466     else if (axis_lat == 0)
467       viewDir = 180;
468   } else if (axis_long == 0) {  // Longitudinal axis neutral
469     if (axis_lat < 0)
470       viewDir = 90;
471     else if (axis_lat > 0)
472       viewDir = 270;
473     else return; /* And assertion failure maybe? */
474   }
475
476                                 // Do all the difficult cases
477   if ( viewDir > 900 )
478     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
479   if ( viewDir < -1 ) viewDir += 360;
480
481   get_current_view()->setGoalHeadingOffset_deg(viewDir);
482 }