]> git.mxchange.org Git - flightgear.git/blob - src/Viewer/viewmgr.cxx
Code cleanups, code updates and fix at least on (possible) devide-by-zero
[flightgear.git] / src / Viewer / 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  - http://www.flightgear.org/~curt
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 // $Id$
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "viewmgr.hxx"
29
30 #include <simgear/compiler.h>
31 #include <simgear/scene/util/OsgMath.hxx>
32
33 #include <Main/fg_props.hxx>
34 #include "view.hxx"
35
36 #include "CameraGroup.hxx"
37
38 // Constructor
39 FGViewMgr::FGViewMgr( void ) :
40   inited(false),
41   config_list(fgGetNode("/sim", true)->getChildren("view")),
42   current(0)
43 {
44 }
45
46 // Destructor
47 FGViewMgr::~FGViewMgr( void )
48 {
49 }
50
51 void
52 FGViewMgr::init ()
53 {
54   if (inited) {
55     SG_LOG(SG_VIEW, SG_WARN, "duplicate init of view manager");
56     return;
57   }
58
59   inited = true;
60
61   for (unsigned int i = 0; i < config_list.size(); i++) {
62     SGPropertyNode *n = config_list[i];
63     SGPropertyNode *config = n->getChild("config", 0, true);
64
65       flightgear::View* v = flightgear::View::createFromProperties(config);
66       if (v) {
67           add_view(v);
68       }
69   }
70
71     get_current_view()->bind();
72 }
73
74 void
75 FGViewMgr::postinit()
76 {
77     // force update now so many properties of the current view are valid,
78     // eg view position and orientation (as exposed via globals)
79     update(0.0);
80 }
81
82 void
83 FGViewMgr::shutdown()
84 {
85     if (!inited) {
86         return;
87     }
88
89     inited = false;
90     views.clear();
91 }
92
93 void
94 FGViewMgr::reinit ()
95 {
96     viewer_list::iterator it;
97     for (it = views.begin(); it != views.end(); ++it) {
98         (*it)->resetOffsetsAndFOV();
99     }
100 }
101
102 void
103 FGViewMgr::bind()
104 {
105     // these are bound to the current view properties
106     _tiedProperties.setRoot(fgGetNode("/sim/current-view", true));
107
108
109     _tiedProperties.Tie("view-number", this,
110                         &FGViewMgr::getView, &FGViewMgr::setView, false);
111     _viewNumberProp = _tiedProperties.getRoot()->getNode("view-number");
112     _viewNumberProp->setAttribute(SGPropertyNode::ARCHIVE, false);
113     _viewNumberProp->setAttribute(SGPropertyNode::PRESERVE, true);
114 }
115
116
117 void
118 FGViewMgr::unbind ()
119 {
120     flightgear::View* v = get_current_view();
121     if (v) {
122         v->unbind();
123     }
124
125   _tiedProperties.Untie();
126     _viewNumberProp.clear();
127 }
128
129 void
130 FGViewMgr::update (double dt)
131 {
132     flightgear::View* currentView = get_current_view();
133     if (!currentView) {
134         return;
135     }
136
137   // Update the current view
138   currentView->update(dt);
139
140
141 // update the camera now
142     osg::ref_ptr<flightgear::CameraGroup> cameraGroup = flightgear::CameraGroup::getDefault();
143     cameraGroup->update(toOsg(currentView->getViewPosition()),
144                         toOsg(currentView->getViewOrientation()));
145     cameraGroup->setCameraParameters(currentView->get_v_fov(),
146                                      cameraGroup->getMasterAspectRatio());
147 }
148
149 void FGViewMgr::clear()
150 {
151     views.clear();
152 }
153
154 flightgear::View*
155 FGViewMgr::get_current_view()
156 {
157     if ( current < (int)views.size() ) {
158         return views[current];
159     } else {
160         return NULL;
161     }
162 }
163
164 const flightgear::View*
165 FGViewMgr::get_current_view() const
166 {
167     if ( current < (int)views.size() ) {
168         return views[current];
169     } else {
170         return NULL;
171     }
172 }
173
174
175 flightgear::View*
176 FGViewMgr::get_view( int i )
177 {
178     if ( i < 0 ) { i = 0; }
179     if ( i >= (int)views.size() ) { i = views.size() - 1; }
180     return views[i];
181 }
182
183 const flightgear::View*
184 FGViewMgr::get_view( int i ) const
185 {
186     if ( i < 0 ) { i = 0; }
187     if ( i >= (int)views.size() ) { i = views.size() - 1; }
188     return views[i];
189 }
190
191 flightgear::View*
192 FGViewMgr::next_view()
193 {
194     setView((current+1 < (int)views.size()) ? (current + 1) : 0);
195     _viewNumberProp->fireValueChanged();
196     return views[current];
197 }
198
199 flightgear::View*
200 FGViewMgr::prev_view()
201 {
202     setView((0 < current) ? (current - 1) : (views.size() - 1));
203     _viewNumberProp->fireValueChanged();
204     return views[current];
205 }
206
207 void
208 FGViewMgr::add_view( flightgear::View * v )
209 {
210   views.push_back(v);
211   v->init();
212 }
213
214 int FGViewMgr::getView () const
215 {
216   return current;
217 }
218
219 void
220 FGViewMgr::setView (int newview)
221 {
222     if (newview == current) {
223         return;
224     }
225
226   // negative numbers -> set view with node index -newview
227   if (newview < 0) {
228     for (int i = 0; i < (int)config_list.size(); i++) {
229       int index = -config_list[i]->getIndex();
230       if (index == newview)
231         newview = i;
232     }
233     if (newview < 0)
234       return;
235   }
236
237   // if newview number too low wrap to last view...
238   if (newview < 0)
239     newview = (int)views.size() - 1;
240
241   // if newview number to high wrap to zero...
242   if (newview >= (int)views.size())
243     newview = 0;
244
245     if (get_current_view()) {
246         get_current_view()->unbind();
247     }
248
249   // set new view
250   current = newview;
251
252     if (get_current_view()) {
253         get_current_view()->bind();
254     }
255
256     // force an update now, to avoid returning bogus data.
257     // real fix would to be make all the accessors use the dirty mechanism
258     // on FGViewer, so update() is a no-op.
259     update(0.0);
260 }