1
0
Fork 0

NavDisplay enhancements for Syd.

- Support text-enable condition on symbols
- support <limit>N</limit> on symbols to restrict
to closest N symbol instances.
- change search to hopefully be more stable at
larger ranges.
This commit is contained in:
James Turner 2012-05-17 17:30:30 +01:00
parent ffac5ff889
commit caf0138ab3
2 changed files with 90 additions and 26 deletions

View file

@ -212,6 +212,7 @@ public:
} }
} // of matches parsing } // of matches parsing
return true; return true;
} }
@ -240,29 +241,37 @@ public:
return true; return true;
} }
void checkEnabled() // return if the enabled state changed (needs a cache update)
bool checkEnabled()
{ {
if (enable.get()) { if (enable.get()) {
bool wasEnabled = enabled;
enabled = enable->test(); enabled = enable->test();
return (enabled != wasEnabled);
} else { } else {
enabled = true; enabled = true;
return false;
} }
} }
bool enabled; // cached enabled state bool enabled; // cached enabled state
std::string type; std::string type;
// record instances for limiting by count
int instanceCount;
private: private:
SymbolDef* definition; SymbolDef* definition;
std::auto_ptr<SGCondition> enable; std::auto_ptr<SGCondition> enable;
string_set required_states; string_set required_states;
string_set excluded_states; string_set excluded_states;
}; };
class SymbolDef class SymbolDef
{ {
public: public:
SymbolDef() : limitCount(0) { }
bool initFromNode(SGPropertyNode* node, NavDisplay* owner) bool initFromNode(SGPropertyNode* node, NavDisplay* owner)
{ {
if (node->getChild("type")) { if (node->getChild("type")) {
@ -306,6 +315,11 @@ public:
textOffset.x() = node->getFloatValue("text-offset-x", 0); textOffset.x() = node->getFloatValue("text-offset-x", 0);
textOffset.y() = node->getFloatValue("text-offset-y", 0); textOffset.y() = node->getFloatValue("text-offset-y", 0);
textColor = readColor(node->getChild("text-color"), color); textColor = readColor(node->getChild("text-color"), color);
SGPropertyNode* enableNode = node->getChild("text-enable");
if (enableNode) {
textEnable.reset(sgReadCondition(fgGetNode("/"), enableNode));
}
} }
drawLine = node->getBoolValue("draw-line", false); drawLine = node->getBoolValue("draw-line", false);
@ -320,6 +334,11 @@ public:
stretchV3 = node->getFloatValue("v3") / texSize; stretchV3 = node->getFloatValue("v3") / texSize;
} }
SGPropertyNode* limitNode = node->getChild("limit");
if (limitNode) {
limitCount = limitNode->getIntValue();
}
return true; return true;
} }
@ -332,6 +351,8 @@ public:
bool rotateToHeading; bool rotateToHeading;
bool roundPos; ///< should position be rounded to integer values bool roundPos; ///< should position be rounded to integer values
bool hasText; bool hasText;
std::auto_ptr<SGCondition> textEnable;
bool textEnabled; ///< cache condition result
osg::Vec4 textColor; osg::Vec4 textColor;
osg::Vec2 textOffset; osg::Vec2 textOffset;
osgText::Text::AlignmentType alignment; osgText::Text::AlignmentType alignment;
@ -350,6 +371,7 @@ public:
bool drawRouteLeg; bool drawRouteLeg;
int limitCount, instanceCount;
}; };
class SymbolInstance class SymbolInstance
@ -420,7 +442,8 @@ NavDisplay::NavDisplay(SGPropertyNode *node) :
_view_heading(0), _view_heading(0),
_font_size(0), _font_size(0),
_font_spacing(0), _font_spacing(0),
_rangeNm(0) _rangeNm(0),
_maxSymbols(100)
{ {
_Instrument = fgGetNode(string("/instrumentation/" + _name).c_str(), _num, true); _Instrument = fgGetNode(string("/instrumentation/" + _name).c_str(), _num, true);
_font_node = _Instrument->getNode("font", true); _font_node = _Instrument->getNode("font", true);
@ -695,8 +718,19 @@ NavDisplay::update (double delta_time_sec)
} }
_symbols.clear(); _symbols.clear();
BOOST_FOREACH(SymbolDef* d, _definitions) {
d->instanceCount = 0;
d->textEnabled = d->textEnable.get() ? d->textEnable->test() : true;
}
bool enableChanged = false;
BOOST_FOREACH(SymbolRule* r, _rules) { BOOST_FOREACH(SymbolRule* r, _rules) {
r->checkEnabled(); enableChanged |= r->checkEnabled();
}
if (enableChanged) {
SG_LOG(SG_INSTR, SG_INFO, "NS rule enables changed, rebuilding cache");
_cachedItemsValid = false;
} }
if (_testModeNode->getBoolValue()) { if (_testModeNode->getBoolValue()) {
@ -858,14 +892,15 @@ public:
void NavDisplay::limitDisplayedSymbols() void NavDisplay::limitDisplayedSymbols()
{ {
unsigned int maxSymbols = _Instrument->getIntValue("max-symbols", 100); // gloabl symbol limit
if (_symbols.size() <= maxSymbols) { _maxSymbols= _Instrument->getIntValue("max-symbols", _maxSymbols);
if ((int) _symbols.size() <= _maxSymbols) {
_excessDataNode->setBoolValue(false); _excessDataNode->setBoolValue(false);
return; return;
} }
std::sort(_symbols.begin(), _symbols.end(), OrderByPriority()); std::sort(_symbols.begin(), _symbols.end(), OrderByPriority());
_symbols.resize(maxSymbols); _symbols.resize(_maxSymbols);
_excessDataNode->setBoolValue(true); _excessDataNode->setBoolValue(true);
} }
@ -912,6 +947,8 @@ osg::Vec2 NavDisplay::projectGeod(const SGGeod& geod) const
class Filter : public FGPositioned::Filter class Filter : public FGPositioned::Filter
{ {
public: public:
Filter(NavDisplay* nd) : _owner(nd) { }
double minRunwayLengthFt; double minRunwayLengthFt;
virtual bool pass(FGPositioned* aPos) const virtual bool pass(FGPositioned* aPos) const
@ -931,7 +968,8 @@ public:
} }
} }
return true; // check against current rule states
return _owner->isPositionedShown(aPos);
} }
virtual FGPositioned::Type minType() const { virtual FGPositioned::Type minType() const {
@ -941,18 +979,24 @@ public:
virtual FGPositioned::Type maxType() const { virtual FGPositioned::Type maxType() const {
return FGPositioned::OBSTACLE; return FGPositioned::OBSTACLE;
} }
private:
NavDisplay* _owner;
}; };
void NavDisplay::findItems() void NavDisplay::findItems()
{ {
if (!_cachedItemsValid) { if (!_cachedItemsValid) {
Filter filt; Filter filt(this);
filt.minRunwayLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 2000); filt.minRunwayLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 2000);
_itemsInRange = FGPositioned::findWithinRange(_pos, _rangeNm, &filt); _itemsInRange = FGPositioned::findClosestN(_pos, _maxSymbols, _rangeNm, &filt);
_cachedItemsValid = true; _cachedItemsValid = true;
_cachedPos = SGVec3d::fromGeod(_pos); _cachedPos = SGVec3d::fromGeod(_pos);
} }
// sort by distance from pos, so symbol limits are accurate
FGPositioned::sortByRange(_itemsInRange, _pos);
BOOST_FOREACH(FGPositioned* pos, _itemsInRange) { BOOST_FOREACH(FGPositioned* pos, _itemsInRange) {
foundPositionedItem(pos); foundPositionedItem(pos);
} }
@ -1098,14 +1142,16 @@ void NavDisplay::findRules(const string& type, const string_set& states, SymbolR
} }
} }
void NavDisplay::foundPositionedItem(FGPositioned* pos) bool NavDisplay::isPositionedShown(FGPositioned* pos)
{ {
if (!pos) { SymbolRuleVector rules;
return; isPositionedShownInner(pos, rules);
return !rules.empty();
} }
void NavDisplay::isPositionedShownInner(FGPositioned* pos, SymbolRuleVector& rules)
{
string type = FGPositioned::nameForType(pos->type()); string type = FGPositioned::nameForType(pos->type());
//boost::to_lower(type);
if (!anyRuleForType(type)) { if (!anyRuleForType(type)) {
return; // not diplayed at all, we're done return; // not diplayed at all, we're done
} }
@ -1113,10 +1159,19 @@ void NavDisplay::foundPositionedItem(FGPositioned* pos)
string_set states; string_set states;
computePositionedState(pos, states); computePositionedState(pos, states);
SymbolRuleVector rules;
findRules(type, states, rules); findRules(type, states, rules);
}
void NavDisplay::foundPositionedItem(FGPositioned* pos)
{
if (!pos) {
return;
}
SymbolRuleVector rules;
isPositionedShownInner(pos, rules);
if (rules.empty()) { if (rules.empty()) {
return; // no rules matched, we can skip this item return;
} }
SGPropertyNode_ptr vars(new SGPropertyNode); SGPropertyNode_ptr vars(new SGPropertyNode);
@ -1317,6 +1372,11 @@ SymbolInstance* NavDisplay::addSymbolInstance(const osg::Vec2& proj, double head
return NULL; return NULL;
} }
if ((def->limitCount > 0) && (def->instanceCount >= def->limitCount)) {
return NULL;
}
++def->instanceCount;
SymbolInstance* sym = new SymbolInstance(proj, heading, def, vars); SymbolInstance* sym = new SymbolInstance(proj, heading, def, vars);
_symbols.push_back(sym); _symbols.push_back(sym);
return sym; return sym;

View file

@ -76,6 +76,8 @@ public:
void forceUpdate() void forceUpdate()
{ _forceUpdate = true; } { _forceUpdate = true; }
bool anyRuleForType(const std::string& type) const;
bool isPositionedShown(FGPositioned* pos);
protected: protected:
std::string _name; std::string _name;
int _num; int _num;
@ -107,6 +109,7 @@ private:
void limitDisplayedSymbols(); void limitDisplayedSymbols();
void findItems(); void findItems();
void isPositionedShownInner(FGPositioned* pos, SymbolRuleVector& rules);
void foundPositionedItem(FGPositioned* pos); void foundPositionedItem(FGPositioned* pos);
void computePositionedPropsAndHeading(FGPositioned* pos, SGPropertyNode* nd, double& heading); void computePositionedPropsAndHeading(FGPositioned* pos, SGPropertyNode* nd, double& heading);
void computePositionedState(FGPositioned* pos, string_set& states); void computePositionedState(FGPositioned* pos, string_set& states);
@ -117,7 +120,7 @@ private:
void processAI(); void processAI();
void computeAIStates(const SGPropertyNode* ai, string_set& states); void computeAIStates(const SGPropertyNode* ai, string_set& states);
bool anyRuleForType(const std::string& type) const;
bool anyRuleMatches(const std::string& type, const string_set& states) const; bool anyRuleMatches(const std::string& type, const string_set& states) const;
void findRules(const std::string& type, const string_set& states, SymbolRuleVector& rules); void findRules(const std::string& type, const string_set& states, SymbolRuleVector& rules);
@ -189,6 +192,7 @@ private:
SGVec3d _cachedPos; SGVec3d _cachedPos;
FGPositioned::List _itemsInRange; FGPositioned::List _itemsInRange;
SGPropertyNode_ptr _excessDataNode; SGPropertyNode_ptr _excessDataNode;
int _maxSymbols;
class CacheListener; class CacheListener;
std::auto_ptr<CacheListener> _cacheListener; std::auto_ptr<CacheListener> _cacheListener;