"Fossies" - the Fresh Open Source Software Archive

Member "flightgear-2020.3.8/src/Viewer/viewmgr.cxx" (24 Mar 2021, 8342 Bytes) of package /linux/privat/flightgear-2020.3.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "viewmgr.cxx" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2020.3.7_vs_2020.3.8.

    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 #include "config.h"
   25 
   26 #include <algorithm> // for std::clamp
   27 
   28 #include "viewmgr.hxx"
   29 #include "ViewPropertyEvaluator.hxx"
   30 
   31 #include <simgear/compiler.h>
   32 #include <simgear/scene/util/OsgMath.hxx>
   33 #include <simgear/structure/exception.hxx>
   34 
   35 #include <Main/fg_props.hxx>
   36 #include "view.hxx"
   37 
   38 #include "CameraGroup.hxx"
   39 
   40 namespace {
   41 
   42 template <typename T>
   43 T not_std_clamp(const T& v, const T& lower, const T& upper)
   44 {
   45     return (v < lower) ? lower : ((v > upper) ? upper : v);
   46 }
   47 
   48 } // namespace
   49 
   50 // Constructor
   51 FGViewMgr::FGViewMgr( void ) :
   52   config_list(fgGetNode("/sim", true)->getChildren("view"))
   53 {
   54     _current = fgGetInt("/sim/current-view/view-number");
   55 }
   56 
   57 // Destructor
   58 FGViewMgr::~FGViewMgr( void )
   59 {
   60 }
   61 
   62 void
   63 FGViewMgr::init ()
   64 {
   65     if (_inited) {
   66         SG_LOG(SG_VIEW, SG_WARN, "duplicate init of view manager");
   67         return;
   68     }
   69 
   70     _inited = true;
   71 
   72     // Ensure that /sim/chase-distance-m is negative if it is specified.
   73     // E.g. see https://sourceforge.net/p/flightgear/codetickets/2454/
   74     //
   75     SGPropertyNode* chase_distance_node = fgGetNode("/sim/chase-distance-m");
   76     if (chase_distance_node) {
   77         double chase_distance = chase_distance_node->getDoubleValue();
   78         if (chase_distance > 0) {
   79             chase_distance = -chase_distance;
   80             SG_LOG(SG_VIEW, SG_ALERT, "sim/chase-distance-m is positive; correcting to " << chase_distance);
   81             chase_distance_node->setDoubleValue(chase_distance);
   82         }
   83     }
   84 
   85     config_list = fgGetNode("/sim", true)->getChildren("view");
   86     _current = fgGetInt("/sim/current-view/view-number");
   87     if (_current != 0 && (_current < 0 || _current >= (int) views.size())) {
   88         SG_LOG(SG_VIEW, SG_ALERT,
   89                 "Invalid /sim/current-view/view-number=" << _current
   90                 << ". views.size()=" << views.size()
   91                 << ". Will assert false and use zero."
   92                 );
   93         assert(0);
   94         _current = 0;
   95     }
   96 
   97     for (unsigned int i = 0; i < config_list.size(); i++) {
   98         SGPropertyNode* n = config_list[i];
   99         SGPropertyNode* config = n->getChild("config", 0, true);
  100 
  101         flightgear::View* v = flightgear::View::createFromProperties(config, n->getIndex());
  102         if (v) {
  103             add_view(v);
  104         } else {
  105             SG_LOG(SG_VIEW, SG_DEV_WARN, "Failed to create view from:" << config->getPath());
  106         }
  107   }
  108 
  109   if (get_current_view()) {
  110       get_current_view()->bind();
  111   } else {
  112       SG_LOG(SG_VIEW, SG_DEV_WARN, "FGViewMgr::init: current view " << _current << " failed to create");
  113   }
  114 }
  115 
  116 void
  117 FGViewMgr::postinit()
  118 {
  119     // force update now so many properties of the current view are valid,
  120     // eg view position and orientation (as exposed via globals)
  121     update(0.0);
  122 }
  123 
  124 void
  125 FGViewMgr::shutdown()
  126 {
  127     if (!_inited) {
  128         return;
  129     }
  130 
  131     _inited = false;
  132     views.clear();
  133 }
  134 
  135 void
  136 FGViewMgr::reinit ()
  137 {
  138     viewer_list::iterator it;
  139     for (it = views.begin(); it != views.end(); ++it) {
  140         (*it)->resetOffsetsAndFOV();
  141     }
  142 }
  143 
  144 void
  145 FGViewMgr::bind()
  146 {
  147     // these are bound to the current view properties
  148     _tiedProperties.setRoot(fgGetNode("/sim/current-view", true));
  149 
  150 
  151     _tiedProperties.Tie("view-number", this,
  152                         &FGViewMgr::getCurrentViewIndex,
  153                         &FGViewMgr::setCurrentViewIndex, false);
  154     _viewNumberProp = _tiedProperties.getRoot()->getNode("view-number");
  155     _viewNumberProp->setAttribute(SGPropertyNode::ARCHIVE, false);
  156     _viewNumberProp->setAttribute(SGPropertyNode::PRESERVE, true);
  157     _viewNumberProp->setAttribute(SGPropertyNode::LISTENER_SAFE, true);
  158 }
  159 
  160 
  161 void
  162 FGViewMgr::unbind ()
  163 {
  164     flightgear::View* v = get_current_view();
  165     if (v) {
  166         v->unbind();
  167     }
  168 
  169   _tiedProperties.Untie();
  170     _viewNumberProp.clear();
  171     
  172     ViewPropertyEvaluator::clear();
  173 }
  174 
  175 void
  176 FGViewMgr::update (double dt)
  177 {
  178     flightgear::View* currentView = get_current_view();
  179     if (!currentView) {
  180         return;
  181     }
  182 
  183   // Update the current view
  184   currentView->update(dt);
  185 
  186 // update the camera now
  187     osg::ref_ptr<flightgear::CameraGroup> cameraGroup = flightgear::CameraGroup::getDefault();
  188     if (!cameraGroup) {
  189         // attempting to diagnose the cause of FLIGHTGEAR-H9F
  190         throw sg_exception("FGViewMgr::update: no camera group exists");
  191     }
  192 
  193     cameraGroup->setCameraParameters(currentView->get_v_fov(),
  194                                         cameraGroup->getMasterAspectRatio());
  195     cameraGroup->update(toOsg(currentView->getViewPosition()),
  196                         toOsg(currentView->getViewOrientation()));
  197 }
  198 
  199 void FGViewMgr::clear()
  200 {
  201     views.clear();
  202 }
  203 
  204 flightgear::View*
  205 FGViewMgr::get_current_view()
  206 {
  207     if (views.empty())
  208         return nullptr;
  209     assert(_current >= 0 && _current < (int) views.size());
  210     return views[_current];
  211 }
  212 
  213 const flightgear::View*
  214 FGViewMgr::get_current_view() const
  215 {
  216     return const_cast<FGViewMgr*>(this)->get_current_view();
  217 }
  218 
  219 
  220 flightgear::View*
  221 FGViewMgr::get_view( int i )
  222 {
  223     const auto lastView = static_cast<int>(views.size()) - 1;
  224     const int c = not_std_clamp(i, 0, lastView);
  225     return views.at(c);
  226 }
  227 
  228 const flightgear::View*
  229 FGViewMgr::get_view( int i ) const
  230 {
  231     const auto lastView = static_cast<int>(views.size()) - 1;
  232     const int c = not_std_clamp(i, 0, lastView);
  233     return views.at(c);
  234 }
  235 
  236 flightgear::View*
  237 FGViewMgr::next_view()
  238 {
  239     const auto numViews = static_cast<int>(views.size());
  240     setCurrentViewIndex((_current + 1) % numViews);
  241     _viewNumberProp->fireValueChanged();
  242     return get_current_view();
  243 }
  244 
  245 flightgear::View*
  246 FGViewMgr::prev_view()
  247 {
  248     const auto numViews = static_cast<int>(views.size());
  249     // subtract 1, but add a full numViews, to ensure the integer
  250     // modulo returns a +ve result; negative values mean something
  251     // else to setCurrentViewIndex
  252     setCurrentViewIndex((_current - 1 + numViews) % numViews);
  253     _viewNumberProp->fireValueChanged();
  254     return get_current_view();
  255 }
  256 
  257 void
  258 FGViewMgr::add_view( flightgear::View * v )
  259 {
  260   views.push_back(v);
  261   v->init();
  262 }
  263 
  264 int FGViewMgr::getCurrentViewIndex() const
  265 {
  266     return _current;
  267 }
  268 
  269 void FGViewMgr::setCurrentViewIndex(int newview)
  270 {
  271     if (newview == _current) {
  272         return;
  273     }
  274     // negative numbers -> set view with node index -newview
  275     if (newview < 0) {
  276         for (int i = 0; i < (int)config_list.size(); i++) {
  277             int index = -config_list[i]->getIndex();
  278             if (index == newview)
  279                 newview = i;
  280         }
  281         if (newview < 0) {
  282             SG_LOG(SG_VIEW, SG_ALERT,
  283                     "Failed to find -ve newview=" << newview
  284                     << ". Will assert false and ignore."
  285                     );
  286             assert(0);
  287             return;
  288         }
  289     }
  290     if (newview < 0 || newview >= (int) views.size()) {
  291         SG_LOG(SG_VIEW, SG_ALERT, "Invalid newview=" << newview
  292                 << ". views.size()=" << views.size()
  293                 << ". Will assert false and ignore."
  294                 );
  295         assert(0);
  296         return;
  297     }
  298 
  299     if (get_current_view()) {
  300         get_current_view()->unbind();
  301     }
  302 
  303     _current = newview;
  304 
  305     if (get_current_view()) {
  306         get_current_view()->bind();
  307     }
  308 }
  309 
  310 
  311 // Register the subsystem.
  312 SGSubsystemMgr::Registrant<FGViewMgr> registrantFGViewMgr(
  313     SGSubsystemMgr::DISPLAY);