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:
parent
ffac5ff889
commit
caf0138ab3
2 changed files with 90 additions and 26 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue