]> git.mxchange.org Git - flightgear.git/blob - src/Main/viewmgr.cxx
Modified the replay system to work without enabling the master or clock freeze.
[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 "viewmgr.hxx"
29 #include "fg_props.hxx"
30
31
32 // Constructor
33 FGViewMgr::FGViewMgr( void ) :
34   axis_long(0),
35   axis_lat(0),
36   current(0)
37 {
38 }
39
40
41 // Destructor
42 FGViewMgr::~FGViewMgr( void ) {
43 }
44
45 void
46 FGViewMgr::init ()
47 {
48   char stridx [ 20 ];
49   string viewpath, nodepath, strdata;
50   bool from_model = false;
51   bool at_model = false;
52   int from_model_index = 0;
53   int at_model_index = 0;
54   double damp_alt, damp_roll, damp_pitch, damp_heading;
55   double x_offset_m, y_offset_m, z_offset_m, fov_deg;
56   double heading_offset_deg, pitch_offset_deg, roll_offset_deg;
57   double target_x_offset_m, target_y_offset_m, target_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         // view damping (0.0: no damping; <0.0: all but alt; >0.0: damp all)
98         nodepath = viewpath;
99         nodepath += "/config/at-model-alt-damping";
100         damp_alt = fgGetDouble(nodepath.c_str(), 0.0);
101
102         nodepath = viewpath;
103         nodepath += "/config/at-model-roll-damping";
104         damp_roll = fgGetDouble(nodepath.c_str(), 0.0);
105
106         nodepath = viewpath;
107         nodepath += "/config/at-model-pitch-damping";
108         damp_pitch = fgGetDouble(nodepath.c_str(), 0.0);
109
110         nodepath = viewpath;
111         nodepath += "/config/at-model-heading-damping";
112         damp_heading = fgGetDouble(nodepath.c_str(), 0.0);
113       }
114     }
115
116     nodepath = viewpath;
117     nodepath += "/config/x-offset-m";
118     x_offset_m = fgGetDouble(nodepath.c_str());
119     nodepath = viewpath;
120     nodepath += "/config/y-offset-m";
121     y_offset_m = fgGetDouble(nodepath.c_str());
122     nodepath = viewpath;
123     nodepath += "/config/z-offset-m";
124     z_offset_m = fgGetDouble(nodepath.c_str());
125     nodepath = viewpath;
126     nodepath += "/config/pitch-offset-deg";
127     pitch_offset_deg = fgGetDouble(nodepath.c_str());
128     fgSetDouble(nodepath.c_str(),pitch_offset_deg);
129     nodepath = viewpath;
130     nodepath += "/config/heading-offset-deg";
131     heading_offset_deg = fgGetDouble(nodepath.c_str());
132     fgSetDouble(nodepath.c_str(),heading_offset_deg);
133     nodepath = viewpath;
134     nodepath += "/config/roll-offset-deg";
135     roll_offset_deg = fgGetDouble(nodepath.c_str());
136     fgSetDouble(nodepath.c_str(),roll_offset_deg);
137     nodepath = viewpath;
138     nodepath += "/config/default-field-of-view-deg";
139     fov_deg = fgGetDouble(nodepath.c_str());
140
141     // target offsets for lookat mode only...
142     nodepath = viewpath;
143     nodepath += "/config/target-x-offset-m";
144     target_x_offset_m = fgGetDouble(nodepath.c_str());
145     nodepath = viewpath;
146     nodepath += "/config/target-y-offset-m";
147     target_y_offset_m = fgGetDouble(nodepath.c_str());
148     nodepath = viewpath;
149     nodepath += "/config/target-z-offset-m";
150     target_z_offset_m = fgGetDouble(nodepath.c_str());
151
152     nodepath = viewpath;
153     nodepath += "/config/ground-level-nearplane-m";
154     near_m = fgGetDouble(nodepath.c_str());
155
156     // supporting two types now "lookat" = 1 and "lookfrom" = 0
157     if ( strcmp("lookat",strdata.c_str()) == 0 )
158       add_view(new FGViewer ( FG_LOOKAT, from_model, from_model_index,
159                               at_model, at_model_index,
160                               damp_alt, damp_roll, damp_pitch, damp_heading,
161                               x_offset_m, y_offset_m,z_offset_m,
162                               heading_offset_deg, pitch_offset_deg,
163                               roll_offset_deg, fov_deg,
164                               target_x_offset_m, target_y_offset_m,
165                               target_z_offset_m, near_m ));
166     else
167       add_view(new FGViewer ( FG_LOOKFROM, from_model, from_model_index,
168                               false, 0, 0.0, 0.0, 0.0, 0.0,
169                               x_offset_m, y_offset_m, z_offset_m,
170                               heading_offset_deg, pitch_offset_deg,
171                               roll_offset_deg, fov_deg, 0, 0, 0, near_m ));
172   }
173
174   copyToCurrent();
175   
176 }
177
178 void
179 FGViewMgr::reinit ()
180 {
181   char stridx [ 20 ];
182   string viewpath, nodepath, strdata;
183   double fov_deg;
184
185   // reset offsets and fov to configuration defaults
186
187   for (int i = 0; i < fgGetInt("/sim/number-views"); i++) {
188     viewpath = "/sim/view";
189     sprintf(stridx, "[%d]", i);
190     viewpath += stridx;
191
192     setView(i);
193
194     nodepath = viewpath;
195     nodepath += "/config/x-offset-m";
196     fgSetDouble("/sim/current-view/x-offset-m",fgGetDouble(nodepath.c_str()));
197
198     nodepath = viewpath;
199     nodepath += "/config/y-offset-m";
200     fgSetDouble("/sim/current-view/y-offset-m",fgGetDouble(nodepath.c_str()));
201
202     nodepath = viewpath;
203     nodepath += "/config/z-offset-m";
204     fgSetDouble("/sim/current-view/z-offset-m",fgGetDouble(nodepath.c_str()));
205
206     nodepath = viewpath;
207     nodepath += "/config/pitch-offset-deg";
208     fgSetDouble("/sim/current-view/pitch-offset-deg",
209                 fgGetDouble(nodepath.c_str()));
210
211     nodepath = viewpath;
212     nodepath += "/config/heading-offset-deg";
213     fgSetDouble("/sim/current-view/heading-offset-deg",
214                 fgGetDouble(nodepath.c_str()));
215
216     nodepath = viewpath;
217     nodepath += "/config/roll-offset-deg";
218     fgSetDouble("/sim/current-view/roll-offset-deg",
219                 fgGetDouble(nodepath.c_str()));
220
221     nodepath = viewpath;
222     nodepath += "/config/default-field-of-view-deg";
223     fov_deg = fgGetDouble(nodepath.c_str());
224     if (fov_deg < 10.0) {
225       fov_deg = 55.0;
226     }
227     fgSetDouble("/sim/current-view/field-of-view",fov_deg);
228
229     // target offsets for lookat mode only...
230     nodepath = viewpath;
231     nodepath += "/config/target-x-offset-m";
232     fgSetDouble("/sim/current-view/target-x-offset-deg",
233                 fgGetDouble(nodepath.c_str()));
234
235     nodepath = viewpath;
236     nodepath += "/config/target-y-offset-m";
237     fgSetDouble("/sim/current-view/target-y-offset-deg",
238                 fgGetDouble(nodepath.c_str()));
239
240     nodepath = viewpath;
241     nodepath += "/config/target-z-offset-m";
242     fgSetDouble("/sim/current-view/target-z-offset-deg",
243                 fgGetDouble(nodepath.c_str()));
244
245  }
246
247     setView(0);
248
249 }
250
251 typedef double (FGViewMgr::*double_getter)() const;
252
253 void
254 FGViewMgr::bind ()
255 {
256   // these are bound to the current view properties
257   fgTie("/sim/current-view/heading-offset-deg", this,
258         &FGViewMgr::getViewHeadingOffset_deg,
259         &FGViewMgr::setViewHeadingOffset_deg);
260   fgSetArchivable("/sim/current-view/heading-offset-deg");
261   fgTie("/sim/current-view/goal-heading-offset-deg", this,
262         &FGViewMgr::getViewGoalHeadingOffset_deg,
263         &FGViewMgr::setViewGoalHeadingOffset_deg);
264   fgSetArchivable("/sim/current-view/goal-heading-offset-deg");
265   fgTie("/sim/current-view/pitch-offset-deg", this,
266         &FGViewMgr::getViewPitchOffset_deg,
267         &FGViewMgr::setViewPitchOffset_deg);
268   fgSetArchivable("/sim/current-view/pitch-offset-deg");
269   fgTie("/sim/current-view/goal-pitch-offset-deg", this,
270         &FGViewMgr::getGoalViewPitchOffset_deg,
271         &FGViewMgr::setGoalViewPitchOffset_deg);
272   fgSetArchivable("/sim/current-view/goal-pitch-offset-deg");
273
274   fgTie("/sim/current-view/view-number", this, 
275                       &FGViewMgr::getView, &FGViewMgr::setView);
276   fgSetArchivable("/sim/current-view/view-number", FALSE);
277
278   fgTie("/sim/current-view/axes/long", this,
279         (double_getter)0, &FGViewMgr::setViewAxisLong);
280   fgSetArchivable("/sim/current-view/axes/long");
281
282   fgTie("/sim/current-view/axes/lat", this,
283         (double_getter)0, &FGViewMgr::setViewAxisLat);
284   fgSetArchivable("/sim/current-view/axes/lat");
285
286   fgTie("/sim/current-view/field-of-view", this,
287         &FGViewMgr::getFOV_deg, &FGViewMgr::setFOV_deg);
288   fgSetArchivable("/sim/current-view/field-of-view");
289
290   fgTie("/sim/current-view/ground-level-nearplane-m", this,
291         &FGViewMgr::getNear_m, &FGViewMgr::setNear_m);
292   fgSetArchivable("/sim/current-view/ground-level-nearplane-m");
293
294 }
295
296 void
297 FGViewMgr::unbind ()
298 {
299   // FIXME:
300   // need to redo these bindings to the new locations (move to viewer?)
301   fgUntie("/sim/current-view/heading-offset-deg");
302   fgUntie("/sim/current-view/goal-heading-offset-deg");
303   fgUntie("/sim/current-view/pitch-offset-deg");
304   fgUntie("/sim/current-view/goal-pitch-offset-deg");
305   fgUntie("/sim/field-of-view");
306   fgUntie("/sim/current-view/view-number");
307   fgUntie("/sim/current-view/axes/long");
308   fgUntie("/sim/current-view/axes/lat");
309   fgUntie("/sim/current-view/ground-level-nearplane-m");
310 }
311
312 void
313 FGViewMgr::update (double dt)
314 {
315   char stridx [20];
316   string viewpath, nodepath;
317   double lon_deg, lat_deg, alt_ft, roll_deg, pitch_deg, heading_deg;
318
319   FGViewer * view = get_current_view();
320   if (view == 0)
321     return;
322
323   // 
324   int i = current;
325   viewpath = "/sim/view";
326   sprintf(stridx, "[%d]", i);
327   viewpath += stridx;
328
329   FGViewer *loop_view = (FGViewer *)get_view( i );
330
331                 // Set up view location and orientation
332
333   nodepath = viewpath;
334   nodepath += "/config/from-model";
335   if (!fgGetBool(nodepath.c_str())) {
336     nodepath = viewpath;
337     nodepath += "/config/eye-lon-deg-path";
338     lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
339     nodepath = viewpath;
340     nodepath += "/config/eye-lat-deg-path";
341     lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
342     nodepath = viewpath;
343     nodepath += "/config/eye-alt-ft-path";
344     alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
345     nodepath = viewpath;
346     nodepath += "/config/eye-roll-deg-path";
347     roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
348     nodepath = viewpath;
349     nodepath += "/config/eye-pitch-deg-path";
350     pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
351     nodepath = viewpath;
352     nodepath += "/config/eye-heading-deg-path";
353     heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
354     loop_view->setPosition(lon_deg, lat_deg, alt_ft);
355     loop_view->setOrientation(roll_deg, pitch_deg, heading_deg);
356   } else {
357     // force recalc in viewer
358     loop_view->set_dirty();
359   }
360
361   // if lookat (type 1) then get target data...
362   if (loop_view->getType() == FG_LOOKAT) {
363     nodepath = viewpath;
364     nodepath += "/config/from-model";
365     if (!fgGetBool(nodepath.c_str())) {
366       nodepath = viewpath;
367       nodepath += "/config/target-lon-deg-path";
368       lon_deg = fgGetDouble(fgGetString(nodepath.c_str()));
369       nodepath = viewpath;
370       nodepath += "/config/target-lat-deg-path";
371       lat_deg = fgGetDouble(fgGetString(nodepath.c_str()));
372       nodepath = viewpath;
373       nodepath += "/config/target-alt-ft-path";
374       alt_ft = fgGetDouble(fgGetString(nodepath.c_str()));
375       nodepath = viewpath;
376       nodepath += "/config/target-roll-deg-path";
377       roll_deg = fgGetDouble(fgGetString(nodepath.c_str()));
378       nodepath = viewpath;
379       nodepath += "/config/target-pitch-deg-path";
380       pitch_deg = fgGetDouble(fgGetString(nodepath.c_str()));
381       nodepath = viewpath;
382       nodepath += "/config/target-heading-deg-path";
383       heading_deg = fgGetDouble(fgGetString(nodepath.c_str()));
384
385       loop_view->setTargetPosition(lon_deg, lat_deg, alt_ft);
386       loop_view->setTargetOrientation(roll_deg, pitch_deg, heading_deg);
387     } else {
388       loop_view->set_dirty();
389     }
390   }
391
392   setViewXOffset_m(fgGetDouble("/sim/current-view/x-offset-m"));
393   setViewYOffset_m(fgGetDouble("/sim/current-view/y-offset-m"));
394   setViewZOffset_m(fgGetDouble("/sim/current-view/z-offset-m"));
395
396   setViewTargetXOffset_m(fgGetDouble("/sim/current-view/target-x-offset-m"));
397   setViewTargetYOffset_m(fgGetDouble("/sim/current-view/target-y-offset-m"));
398   setViewTargetZOffset_m(fgGetDouble("/sim/current-view/target-z-offset-m"));
399
400                                 // Update the current view
401   do_axes();
402   view->update(dt);
403 }
404
405 void
406 FGViewMgr::copyToCurrent()
407 {
408     char stridx [20];
409     string viewpath, nodepath;
410
411     int i = current;
412     viewpath = "/sim/view";
413     sprintf(stridx, "[%d]", i);
414     viewpath += stridx;
415
416     // copy certain view config data for default values
417     nodepath = viewpath;
418     nodepath += "/config/default-heading-offset-deg";
419     fgSetDouble("/sim/current-view/config/heading-offset-deg",
420                 fgGetDouble(nodepath.c_str()));
421
422     nodepath = viewpath;
423     nodepath += "/config/pitch-offset-deg";
424     fgSetDouble("/sim/current-view/config/pitch-offset-deg",
425                 fgGetDouble(nodepath.c_str()));
426
427     nodepath = viewpath;
428     nodepath += "/config/roll-offset-deg";
429     fgSetDouble("/sim/current-view/config/roll-offset-deg",
430                 fgGetDouble(nodepath.c_str()));
431
432     nodepath = viewpath;
433     nodepath += "/config/default-field-of-view-deg";
434     fgSetDouble("/sim/current-view/config/default-field-of-view-deg",
435                 fgGetDouble(nodepath.c_str()));
436
437     // copy view data
438     fgSetDouble("/sim/current-view/x-offset-m", getViewXOffset_m());
439     fgSetDouble("/sim/current-view/y-offset-m", getViewYOffset_m());
440     fgSetDouble("/sim/current-view/z-offset-m", getViewZOffset_m());
441     fgSetDouble("/sim/current-view/goal-heading-offset-deg",
442                 get_current_view()->getGoalHeadingOffset_deg());
443     fgSetDouble("/sim/current-view/goal-pitch-offset-deg",
444                 get_current_view()->getGoalPitchOffset_deg());
445     fgSetDouble("/sim/current-view/goal-roll-offset-deg",
446                 get_current_view()->getRollOffset_deg());
447     fgSetDouble("/sim/current-view/heading-offset-deg",
448                 get_current_view()->getHeadingOffset_deg());
449     fgSetDouble("/sim/current-view/pitch-offset-deg",
450                 get_current_view()->getPitchOffset_deg());
451     fgSetDouble("/sim/current-view/roll-offset-deg",
452                 get_current_view()->getRollOffset_deg());
453     fgSetDouble("/sim/current-view/target-x-offset-m",
454                 get_current_view()->getTargetXOffset_m());
455     fgSetDouble("/sim/current-view/target-y-offset-m",
456                 get_current_view()->getTargetYOffset_m());
457     fgSetDouble("/sim/current-view/target-z-offset-m",
458                 get_current_view()->getTargetZOffset_m());
459 }
460
461
462 double
463 FGViewMgr::getViewHeadingOffset_deg () const
464 {
465   const FGViewer * view = get_current_view();
466   return (view == 0 ? 0 : view->getHeadingOffset_deg());
467 }
468
469 void
470 FGViewMgr::setViewHeadingOffset_deg (double offset)
471 {
472   FGViewer * view = get_current_view();
473   if (view != 0) {
474     view->setGoalHeadingOffset_deg(offset);
475     view->setHeadingOffset_deg(offset);
476   }
477 }
478
479 double
480 FGViewMgr::getViewGoalHeadingOffset_deg () const
481 {
482   const FGViewer * view = get_current_view();
483   return (view == 0 ? 0 : view->getGoalHeadingOffset_deg());
484 }
485
486 void
487 FGViewMgr::setViewGoalHeadingOffset_deg (double offset)
488 {
489   FGViewer * view = get_current_view();
490   if (view != 0)
491     view->setGoalHeadingOffset_deg(offset);
492 }
493
494 double
495 FGViewMgr::getViewPitchOffset_deg () const
496 {
497   const FGViewer * view = get_current_view();
498   return (view == 0 ? 0 : view->getPitchOffset_deg());
499 }
500
501 void
502 FGViewMgr::setViewPitchOffset_deg (double tilt)
503 {
504   FGViewer * view = get_current_view();
505   if (view != 0) {
506     view->setGoalPitchOffset_deg(tilt);
507     view->setPitchOffset_deg(tilt);
508   }
509 }
510
511 double
512 FGViewMgr::getGoalViewPitchOffset_deg () const
513 {
514   const FGViewer * view = get_current_view();
515   return (view == 0 ? 0 : view->getGoalPitchOffset_deg());
516 }
517
518 void
519 FGViewMgr::setGoalViewPitchOffset_deg (double tilt)
520 {
521   FGViewer * view = get_current_view();
522   if (view != 0)
523     view->setGoalPitchOffset_deg(tilt);
524 }
525
526 double
527 FGViewMgr::getViewXOffset_m () const
528 {
529   const FGViewer * view = get_current_view();
530   if (view != 0) {
531     return ((FGViewer *)view)->getXOffset_m();
532   } else {
533     return 0;
534   }
535 }
536
537 void
538 FGViewMgr::setViewXOffset_m (double x)
539 {
540   FGViewer * view = get_current_view();
541   if (view != 0) {
542     view->setXOffset_m(x);
543   }
544 }
545
546 double
547 FGViewMgr::getViewYOffset_m () const
548 {
549   const FGViewer * view = get_current_view();
550   if (view != 0) {
551     return ((FGViewer *)view)->getYOffset_m();
552   } else {
553     return 0;
554   }
555 }
556
557 void
558 FGViewMgr::setViewYOffset_m (double y)
559 {
560   FGViewer * view = get_current_view();
561   if (view != 0) {
562     view->setYOffset_m(y);
563   }
564 }
565
566 double
567 FGViewMgr::getViewZOffset_m () const
568 {
569   const FGViewer * view = get_current_view();
570   if (view != 0) {
571     return ((FGViewer *)view)->getZOffset_m();
572   } else {
573     return 0;
574   }
575 }
576
577 void
578 FGViewMgr::setViewZOffset_m (double z)
579 {
580   FGViewer * view = get_current_view();
581   if (view != 0) {
582     view->setZOffset_m(z);
583   }
584 }
585
586 double
587 FGViewMgr::getViewTargetXOffset_m () const
588 {
589   const FGViewer * view = get_current_view();
590   if (view != 0) {
591     return ((FGViewer *)view)->getTargetXOffset_m();
592   } else {
593     return 0;
594   }
595 }
596
597 void
598 FGViewMgr::setViewTargetXOffset_m (double x)
599 {
600   FGViewer * view = get_current_view();
601   if (view != 0) {
602     view->setTargetXOffset_m(x);
603   }
604 }
605
606 double
607 FGViewMgr::getViewTargetYOffset_m () const
608 {
609   const FGViewer * view = get_current_view();
610   if (view != 0) {
611     return ((FGViewer *)view)->getTargetYOffset_m();
612   } else {
613     return 0;
614   }
615 }
616
617 void
618 FGViewMgr::setViewTargetYOffset_m (double y)
619 {
620   FGViewer * view = get_current_view();
621   if (view != 0) {
622     view->setTargetYOffset_m(y);
623   }
624 }
625
626 double
627 FGViewMgr::getViewTargetZOffset_m () const
628 {
629   const FGViewer * view = get_current_view();
630   if (view != 0) {
631     return ((FGViewer *)view)->getTargetZOffset_m();
632   } else {
633     return 0;
634   }
635 }
636
637 void
638 FGViewMgr::setViewTargetZOffset_m (double z)
639 {
640   FGViewer * view = get_current_view();
641   if (view != 0) {
642     view->setTargetZOffset_m(z);
643   }
644 }
645
646 int
647 FGViewMgr::getView () const
648 {
649   return ( current );
650 }
651
652 void
653 FGViewMgr::setView (int newview )
654 {
655   // if newview number too low wrap to last view...
656   if ( newview < 0 ) {
657     newview = (int)views.size() -1;
658   }
659   // if newview number to high wrap to zero...
660   if ( newview > ((int)views.size() -1) ) {
661     newview = 0;
662   }
663   // set new view
664   set_view( newview );
665   // copy in view data
666   copyToCurrent ();
667 }
668
669
670 double
671 FGViewMgr::getFOV_deg () const
672 {
673   const FGViewer * view = get_current_view();
674   return (view == 0 ? 0 : view->get_fov());
675 }
676
677 void
678 FGViewMgr::setFOV_deg (double fov)
679 {
680   FGViewer * view = get_current_view();
681   if (view != 0)
682     view->set_fov(fov);
683 }
684
685 double
686 FGViewMgr::getNear_m () const
687 {
688   const FGViewer * view = get_current_view();
689   return (view == 0 ? 0.5f : view->getNear_m());
690 }
691
692 void
693 FGViewMgr::setNear_m (double near_m)
694 {
695   FGViewer * view = get_current_view();
696   if (view != 0)
697     view->setNear_m(near_m);
698 }
699
700 void
701 FGViewMgr::setViewAxisLong (double axis)
702 {
703   axis_long = axis;
704 }
705
706 void
707 FGViewMgr::setViewAxisLat (double axis)
708 {
709   axis_lat = axis;
710 }
711
712 void
713 FGViewMgr::do_axes ()
714 {
715                                 // Take no action when hat is centered
716   if ( ( axis_long <  0.01 ) &&
717        ( axis_long > -0.01 ) &&
718        ( axis_lat  <  0.01 ) &&
719        ( axis_lat  > -0.01 )
720      )
721     return;
722
723   double viewDir = 999;
724
725   /* Do all the quick and easy cases */
726   if (axis_long < 0) {          // Longitudinal axis forward
727     if (axis_lat == axis_long)
728       viewDir = fgGetDouble("/sim/view/config/front-left-direction-deg");
729     else if (axis_lat == - axis_long)
730       viewDir = fgGetDouble("/sim/view/config/front-right-direction-deg");
731     else if (axis_lat == 0)
732       viewDir = fgGetDouble("/sim/view/config/front-direction-deg");
733   } else if (axis_long > 0) {   // Longitudinal axis backward
734     if (axis_lat == - axis_long)
735       viewDir = fgGetDouble("/sim/view/config/back-left-direction-deg");
736     else if (axis_lat == axis_long)
737       viewDir = fgGetDouble("/sim/view/config/back-right-direction-deg");
738     else if (axis_lat == 0)
739       viewDir = fgGetDouble("/sim/view/config/back-direction-deg");
740   } else if (axis_long == 0) {  // Longitudinal axis neutral
741     if (axis_lat < 0)
742       viewDir = fgGetDouble("/sim/view/config/left-direction-deg");
743     else if (axis_lat > 0)
744       viewDir = fgGetDouble("/sim/view/config/right-direction-deg");
745     else return; /* And assertion failure maybe? */
746   }
747
748                                 // Do all the difficult cases
749   if ( viewDir > 900 )
750     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axis_lat, -axis_long );
751   if ( viewDir < -1 ) viewDir += 360;
752
753   get_current_view()->setGoalHeadingOffset_deg(viewDir);
754 }