]> git.mxchange.org Git - flightgear.git/blobdiff - src/Instrumentation/NavDisplay.cxx
NavDisplay: fix update lag when switching range or centre.
[flightgear.git] / src / Instrumentation / NavDisplay.cxx
index 8d14cb75295766f093eef7d94ef78b101a115479..45fdc3ba7e4e32ee632e26755ee4ee30c6025ecd 100644 (file)
@@ -162,6 +162,22 @@ private:
     NavDisplay* _nd;
 };
 
+class NavDisplay::ForceUpdateListener : public SGPropertyChangeListener
+{
+public:
+  ForceUpdateListener(NavDisplay *nd) : 
+    _nd(nd)
+  {}
+  
+  virtual void valueChanged (SGPropertyNode * prop)
+  {
+    SG_LOG(SG_INSTR, SG_INFO, "forcing NavDisplay update");
+    _nd->forceUpdate();
+  }
+private:
+  NavDisplay* _nd;
+};
+
 ///////////////////////////////////////////////////////////////////
 
 class SymbolDef
@@ -171,7 +187,7 @@ public:
       enable(NULL)
     {}
   
-    bool initFromNode(SGPropertyNode* node)
+    bool initFromNode(SGPropertyNode* node, NavDisplay* owner)
     {
         type = node->getStringValue("type");
         SGPropertyNode* enableNode = node->getChild("enable");
@@ -203,7 +219,7 @@ public:
         xy1.y()  = node->getFloatValue("y1", 5);
       }
       
-        double texSize = node->getFloatValue("texture-size", 1.0);
+        double texSize = node->getFloatValue("texture-size", owner->textureSize());
         
         uv0.x()  = node->getFloatValue("u0", 0) / texSize;
         uv0.y()  = node->getFloatValue("v0", 0) / texSize;
@@ -233,8 +249,8 @@ public:
         if (stretchSymbol) {
             stretchY2 = node->getFloatValue("y2");
             stretchY3 = node->getFloatValue("y3");
-            stretchV2 = node->getFloatValue("v2");
-            stretchV3 = node->getFloatValue("v3");
+            stretchV2 = node->getFloatValue("v2") / texSize;
+            stretchV3 = node->getFloatValue("v3") / texSize;
         }
       
         return true;
@@ -354,6 +370,7 @@ NavDisplay::NavDisplay(SGPropertyNode *node) :
     _num(node->getIntValue("number", 0)),
     _time(0.0),
     _updateInterval(node->getDoubleValue("update-interval-sec", 0.1)),
+    _forceUpdate(true),
     _odg(0),
     _scale(0),
     _view_heading(0),
@@ -375,12 +392,13 @@ NavDisplay::NavDisplay(SGPropertyNode *node) :
     INITFONT("color/alpha", 1, Float);
 #undef INITFONT
 
+    _textureSize = _Instrument->getNode("symbol-teture-size", true)->getIntValue();
     SGPropertyNode* symbolsNode = node->getNode("symbols");
     SGPropertyNode* symbol;
-  
+
     for (int i = 0; (symbol = symbolsNode->getChild("symbol", i)) != NULL; ++i) {
         SymbolDef* def = new SymbolDef;
-        if (!def->initFromNode(symbol)) {
+        if (!def->initFromNode(symbol, this)) {
           delete def;
           continue;
         }
@@ -400,12 +418,21 @@ NavDisplay::init ()
 {
     _cachedItemsValid = false;
     _cacheListener.reset(new CacheListener(this));
-    
+    _forceUpdateListener.reset(new ForceUpdateListener(this));
+  
     _serviceable_node = _Instrument->getNode("serviceable", true);
     _rangeNode = _Instrument->getNode("range", true);
     _rangeNode->setDoubleValue(40.0);
     _rangeNode->addChangeListener(_cacheListener.get());
-    
+    _rangeNode->addChangeListener(_forceUpdateListener.get());
+  
+    _xCenterNode = _Instrument->getNode("x-center");
+    _xCenterNode->setDoubleValue(0.5);
+    _xCenterNode->addChangeListener(_forceUpdateListener.get());
+    _yCenterNode = _Instrument->getNode("y-center");
+    _yCenterNode->setDoubleValue(0.5);
+    _yCenterNode->addChangeListener(_forceUpdateListener.get());
+  
     // texture name to use in 2D and 3D instruments
     _texture_path = _Instrument->getStringValue("radar-texture-path",
         "Aircraft/Instruments/Textures/od_wxradar.rgb");
@@ -523,11 +550,16 @@ NavDisplay::update (double delta_time_sec)
     return;
   }
   
-  _time += delta_time_sec;
-  if (_time < _updateInterval){
-    return;
+  if (_forceUpdate) {
+    _forceUpdate = false;
+    _time = 0.0;
+  } else {
+    _time += delta_time_sec;
+    if (_time < _updateInterval){
+      return;
+    }
+    _time -= _updateInterval;
   }
-  _time -= _updateInterval;
 
   _rangeNm = _rangeNode->getFloatValue();
   if (_testModeNode->getBoolValue()) {
@@ -538,8 +570,8 @@ NavDisplay::update (double delta_time_sec)
     _view_heading = _Instrument->getFloatValue("heading-up-deg", 0.0);
   }
   
-  double xCenterFrac = _Instrument->getDoubleValue("x-center", 0.5);
-  double yCenterFrac = _Instrument->getDoubleValue("y-center", 0.5);
+  double xCenterFrac = _xCenterNode->getDoubleValue();
+  double yCenterFrac = _yCenterNode->getDoubleValue();
   int pixelSize = _odg->size();
   
   int rangePixels = _Instrument->getIntValue("range-pixels", -1);
@@ -658,7 +690,7 @@ void NavDisplay::addSymbolToScene(SymbolInstance* sym)
     verts[3] = osg::Vec2(def->xy0.x(), def->xy1.y());
     
     if (def->rotateToHeading) {
-        osg::Matrixf m(degRotation(sym->headingDeg));
+        osg::Matrixf m(degRotation(sym->headingDeg - _view_heading));
         for (int i=0; i<4; ++i) {
             verts[i] = mult(verts[i], m);
         }
@@ -686,7 +718,7 @@ void NavDisplay::addSymbolToScene(SymbolInstance* sym)
         stretchVerts[2] = osg::Vec2(def->xy1.x(), def->stretchY3);
         stretchVerts[3] = osg::Vec2(def->xy0.x(), def->stretchY3);
         
-        osg::Matrixf m(degRotation(sym->headingDeg));
+        osg::Matrixf m(degRotation(sym->headingDeg - _view_heading));
         for (int i=0; i<4; ++i) {
             stretchVerts[i] = mult(stretchVerts[i], m);
         }
@@ -1013,8 +1045,17 @@ void NavDisplay::foundPositionedItem(FGPositioned* pos)
     computePositionedPropsAndHeading(pos, vars, heading);
     
     osg::Vec2 projected = projectGeod(pos->geod());
+    if (pos->type() == FGPositioned::RUNWAY) {
+        FGRunway* rwy = (FGRunway*) pos;
+        projected = projectGeod(rwy->threshold());
+    }
+    
     BOOST_FOREACH(SymbolDef* r, rules) {
-        addSymbolInstance(projected, heading, r, vars);
+        SymbolInstance* ins = addSymbolInstance(projected, heading, r, vars);
+        if (pos->type() == FGPositioned::RUNWAY) {
+            FGRunway* rwy = (FGRunway*) pos;
+            ins->endPos = projectGeod(rwy->end());
+        }
     }
 }
 
@@ -1024,6 +1065,7 @@ void NavDisplay::computePositionedPropsAndHeading(FGPositioned* pos, SGPropertyN
     nd->setStringValue("name", pos->name());
     nd->setDoubleValue("elevation-ft", pos->elevation());
     nd->setIntValue("heading-deg", 0);
+    heading = 0.0;
     
     switch (pos->type()) {
     case FGPositioned::VOR:
@@ -1033,11 +1075,12 @@ void NavDisplay::computePositionedPropsAndHeading(FGPositioned* pos, SGPropertyN
         nd->setDoubleValue("frequency-mhz", nav->get_freq());
         
         if (pos == _nav1Station) {
-            nd->setIntValue("heading-deg", _navRadio1Node->getDoubleValue("radials/target-radial-deg"));
+            heading = _navRadio1Node->getDoubleValue("radials/target-radial-deg");
         } else if (pos == _nav2Station) {
-            nd->setIntValue("heading-deg", _navRadio2Node->getDoubleValue("radials/target-radial-deg"));
+            heading = _navRadio2Node->getDoubleValue("radials/target-radial-deg");
         }
         
+        nd->setIntValue("heading-deg", heading);
         break;
     }
 
@@ -1049,7 +1092,8 @@ void NavDisplay::computePositionedPropsAndHeading(FGPositioned* pos, SGPropertyN
         
     case FGPositioned::RUNWAY: {
         FGRunway* rwy = static_cast<FGRunway*>(pos);
-        nd->setDoubleValue("heading-deg", rwy->headingDeg());
+        heading = rwy->headingDeg();
+        nd->setDoubleValue("heading-deg", heading);
         nd->setIntValue("length-ft", rwy->lengthFt());
         nd->setStringValue("airport", rwy->airport()->ident());
         break;
@@ -1187,15 +1231,15 @@ void NavDisplay::computeAIStates(const SGPropertyNode* ai, string_set& states)
     }
 }
 
-bool NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars)
+SymbolInstance* NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars)
 {
     if (isProjectedClipped(proj)) {
-        return false;
+        return NULL;
     }
     
     SymbolInstance* sym = new SymbolInstance(proj, heading, def, vars);
     _symbols.push_back(sym);
-    return true;
+    return sym;
 }
 
 bool NavDisplay::isProjectedClipped(const osg::Vec2& projected) const