1
0
Fork 0

Allow distinct rule and symbol definitions for navDisplays.

This commit is contained in:
James Turner 2012-01-14 17:00:50 +00:00
parent 0b6579e0e4
commit 96cd6018f9
2 changed files with 153 additions and 70 deletions

View file

@ -57,6 +57,8 @@ using std::setw;
using std::setfill; using std::setfill;
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::map;
using std::string;
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
@ -180,19 +182,24 @@ private:
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
class SymbolDef class SymbolRule
{ {
public: public:
SymbolDef() : SymbolRule()
enable(NULL) {
{}
}
bool initFromNode(SGPropertyNode* node, NavDisplay* owner) bool initFromNode(SGPropertyNode* node, NavDisplay* owner)
{ {
if (!node->getChild("type")) {
return false;
}
type = node->getStringValue("type"); type = node->getStringValue("type");
SGPropertyNode* enableNode = node->getChild("enable"); SGPropertyNode* enableNode = node->getChild("enable");
if (enableNode) { if (enableNode) {
enable = sgReadCondition(fgGetNode("/"), enableNode); enable.reset(sgReadCondition(fgGetNode("/"), enableNode));
} }
int n=0; int n=0;
@ -205,6 +212,66 @@ public:
} }
} // of matches parsing } // of matches parsing
return true;
}
void setDefinition(SymbolDef* d)
{
definition = d;
}
SymbolDef* getDefinition() const
{ return definition; }
bool matches(const string_set& states) const
{
BOOST_FOREACH(const string& s, required_states) {
if (states.count(s) == 0) {
return false;
}
}
BOOST_FOREACH(const string& s, excluded_states) {
if (states.count(s) != 0) {
return false;
}
}
return true;
}
void checkEnabled()
{
if (enable.get()) {
enabled = enable->test();
} else {
enabled = true;
}
}
bool enabled; // cached enabled state
std::string type;
private:
SymbolDef* definition;
std::auto_ptr<SGCondition> enable;
string_set required_states;
string_set excluded_states;
};
class SymbolDef
{
public:
bool initFromNode(SGPropertyNode* node, NavDisplay* owner)
{
if (node->getChild("type")) {
SymbolRule* builtinRule = new SymbolRule;
builtinRule->initFromNode(node, owner);
builtinRule->setDefinition(this);
owner->addRule(builtinRule);
}
if (node->hasChild("width")) { if (node->hasChild("width")) {
float w = node->getFloatValue("width"); float w = node->getFloatValue("width");
float h = node->getFloatValue("height", w); float h = node->getFloatValue("height", w);
@ -256,13 +323,6 @@ public:
return true; return true;
} }
SGCondition* enable;
bool enabled; // cached enabled state
std::string type;
string_set required_states;
string_set excluded_states;
osg::Vec2 xy0, xy1; osg::Vec2 xy0, xy1;
osg::Vec2 uv0, uv1; osg::Vec2 uv0, uv1;
osg::Vec4 color; osg::Vec4 color;
@ -290,22 +350,6 @@ public:
bool drawRouteLeg; bool drawRouteLeg;
bool matches(const string_set& states) const
{
BOOST_FOREACH(const string& s, required_states) {
if (states.count(s) == 0) {
return false;
}
}
BOOST_FOREACH(const string& s, excluded_states) {
if (states.count(s) != 0) {
return false;
}
}
return true;
}
}; };
class SymbolInstance class SymbolInstance
@ -396,6 +440,7 @@ NavDisplay::NavDisplay(SGPropertyNode *node) :
SGPropertyNode* symbolsNode = node->getNode("symbols"); SGPropertyNode* symbolsNode = node->getNode("symbols");
SGPropertyNode* symbol; SGPropertyNode* symbol;
map<string, SymbolDef*> definitionDict;
for (int i = 0; (symbol = symbolsNode->getChild("symbol", i)) != NULL; ++i) { for (int i = 0; (symbol = symbolsNode->getChild("symbol", i)) != NULL; ++i) {
SymbolDef* def = new SymbolDef; SymbolDef* def = new SymbolDef;
if (!def->initFromNode(symbol, this)) { if (!def->initFromNode(symbol, this)) {
@ -403,8 +448,38 @@ NavDisplay::NavDisplay(SGPropertyNode *node) :
continue; continue;
} }
_rules.push_back(def); const char* id = symbol->getStringValue("id");
if (id && strlen(id)) {
definitionDict[id] = def;
}
_definitions.push_back(def);
} // of symbol definition parsing } // of symbol definition parsing
SGPropertyNode* rulesNode = node->getNode("rules");
if (rulesNode) {
SGPropertyNode* rule;
for (int i = 0; (rule = rulesNode->getChild("rule", i)) != NULL; ++i) {
SymbolRule* r = new SymbolRule;
if (!r->initFromNode(rule, this)) {
delete r;
continue;
}
const char* id = symbol->getStringValue("symbol");
if (id && strlen(id) && (definitionDict.find(id) != definitionDict.end())) {
r->setDefinition(definitionDict[id]);
} else {
SG_LOG(SG_INSTR, SG_WARN, "symbol rule has missing/unknown definition id:" << id);
delete r;
continue;
}
addRule(r);
} // of symbol rule parsing
}
} }
@ -618,12 +693,8 @@ NavDisplay::update (double delta_time_sec)
} }
_symbols.clear(); _symbols.clear();
BOOST_FOREACH(SymbolDef* def, _rules) { BOOST_FOREACH(SymbolRule* r, _rules) {
if (def->enable) { r->checkEnabled();
def->enabled = def->enable->test();
} else {
def->enabled = true;
}
} }
if (_testModeNode->getBoolValue()) { if (_testModeNode->getBoolValue()) {
@ -915,7 +986,7 @@ void NavDisplay::processRoute()
state.insert("next-wp"); state.insert("next-wp");
} }
SymbolDefVector rules; SymbolRuleVector rules;
findRules("waypoint" , state, rules); findRules("waypoint" , state, rules);
if (rules.empty()) { if (rules.empty()) {
return; // no rules matched, we can skip this item return; // no rules matched, we can skip this item
@ -927,16 +998,16 @@ void NavDisplay::processRoute()
computeWayptPropsAndHeading(wpt, g, vars, heading); computeWayptPropsAndHeading(wpt, g, vars, heading);
osg::Vec2 projected = projectGeod(g); osg::Vec2 projected = projectGeod(g);
BOOST_FOREACH(SymbolDef* r, rules) { BOOST_FOREACH(SymbolRule* r, rules) {
addSymbolInstance(projected, heading, r, vars); addSymbolInstance(projected, heading, r->getDefinition(), vars);
if (r->drawRouteLeg) { if (r->getDefinition()->drawRouteLeg) {
SGGeodVec gv(path.pathForIndex(w)); SGGeodVec gv(path.pathForIndex(w));
if (!gv.empty()) { if (!gv.empty()) {
osg::Vec2 pr = projectGeod(gv[0]); osg::Vec2 pr = projectGeod(gv[0]);
for (unsigned int i=1; i<gv.size(); ++i) { for (unsigned int i=1; i<gv.size(); ++i) {
osg::Vec2 p = projectGeod(gv[i]); osg::Vec2 p = projectGeod(gv[i]);
addLine(pr, p, r->lineColor); addLine(pr, p, r->getDefinition()->lineColor);
pr = p; pr = p;
} }
} }
@ -979,7 +1050,7 @@ FGNavRecord* NavDisplay::processNavRadio(const SGPropertyNode_ptr& radio)
bool NavDisplay::anyRuleForType(const string& type) const bool NavDisplay::anyRuleForType(const string& type) const
{ {
BOOST_FOREACH(SymbolDef* r, _rules) { BOOST_FOREACH(SymbolRule* r, _rules) {
if (!r->enabled) { if (!r->enabled) {
continue; continue;
} }
@ -994,7 +1065,7 @@ bool NavDisplay::anyRuleForType(const string& type) const
bool NavDisplay::anyRuleMatches(const string& type, const string_set& states) const bool NavDisplay::anyRuleMatches(const string& type, const string_set& states) const
{ {
BOOST_FOREACH(SymbolDef* r, _rules) { BOOST_FOREACH(SymbolRule* r, _rules) {
if (!r->enabled || (r->type != type)) { if (!r->enabled || (r->type != type)) {
continue; continue;
} }
@ -1007,9 +1078,9 @@ bool NavDisplay::anyRuleMatches(const string& type, const string_set& states) co
return false; return false;
} }
void NavDisplay::findRules(const string& type, const string_set& states, SymbolDefVector& rules) void NavDisplay::findRules(const string& type, const string_set& states, SymbolRuleVector& rules)
{ {
BOOST_FOREACH(SymbolDef* candidate, _rules) { BOOST_FOREACH(SymbolRule* candidate, _rules) {
if (!candidate->enabled || (candidate->type != type)) { if (!candidate->enabled || (candidate->type != type)) {
continue; continue;
} }
@ -1034,7 +1105,7 @@ void NavDisplay::foundPositionedItem(FGPositioned* pos)
string_set states; string_set states;
computePositionedState(pos, states); computePositionedState(pos, states);
SymbolDefVector rules; SymbolRuleVector rules;
findRules(type, states, rules); findRules(type, states, rules);
if (rules.empty()) { if (rules.empty()) {
return; // no rules matched, we can skip this item return; // no rules matched, we can skip this item
@ -1050,8 +1121,8 @@ void NavDisplay::foundPositionedItem(FGPositioned* pos)
projected = projectGeod(rwy->threshold()); projected = projectGeod(rwy->threshold());
} }
BOOST_FOREACH(SymbolDef* r, rules) { BOOST_FOREACH(SymbolRule* r, rules) {
SymbolInstance* ins = addSymbolInstance(projected, heading, r, vars); SymbolInstance* ins = addSymbolInstance(projected, heading, r->getDefinition(), vars);
if (pos->type() == FGPositioned::RUNWAY) { if (pos->type() == FGPositioned::RUNWAY) {
FGRunway* rwy = (FGRunway*) pos; FGRunway* rwy = (FGRunway*) pos;
ins->endPos = projectGeod(rwy->end()); ins->endPos = projectGeod(rwy->end());
@ -1190,7 +1261,7 @@ void NavDisplay::processAI()
// with fg-positioned. // with fg-positioned.
string_set ss; string_set ss;
computeAIStates(model, ss); computeAIStates(model, ss);
SymbolDefVector rules; SymbolRuleVector rules;
findRules(mapAINodeToType(model), ss, rules); findRules(mapAINodeToType(model), ss, rules);
if (rules.empty()) { if (rules.empty()) {
return; // no rules matched, we can skip this item return; // no rules matched, we can skip this item
@ -1205,8 +1276,8 @@ void NavDisplay::processAI()
model->setIntValue("flight-level", fl * 10); model->setIntValue("flight-level", fl * 10);
osg::Vec2 projected = projectGeod(aiModelPos); osg::Vec2 projected = projectGeod(aiModelPos);
BOOST_FOREACH(SymbolDef* r, rules) { BOOST_FOREACH(SymbolRule* r, rules) {
addSymbolInstance(projected, heading, r, (SGPropertyNode*) model); addSymbolInstance(projected, heading, r->getDefinition(), (SGPropertyNode*) model);
} }
} // of ai models iteration } // of ai models iteration
} }
@ -1258,15 +1329,15 @@ void NavDisplay::addTestSymbol(const std::string& type, const std::string& state
stateSet.insert(s); stateSet.insert(s);
} }
SymbolDefVector rules; SymbolRuleVector rules;
findRules(type, stateSet, rules); findRules(type, stateSet, rules);
if (rules.empty()) { if (rules.empty()) {
return; // no rules matched, we can skip this item return; // no rules matched, we can skip this item
} }
osg::Vec2 projected = projectGeod(pos); osg::Vec2 projected = projectGeod(pos);
BOOST_FOREACH(SymbolDef* r, rules) { BOOST_FOREACH(SymbolRule* r, rules) {
addSymbolInstance(projected, heading, r, vars); addSymbolInstance(projected, heading, r->getDefinition(), vars);
} }
} }
@ -1302,4 +1373,8 @@ void NavDisplay::addTestSymbols()
addTestSymbol("fix", "", a1, 0.0, NULL); addTestSymbol("fix", "", a1, 0.0, NULL);
} }
void NavDisplay::addRule(SymbolRule* r)
{
_rules.push_back(r);
}

View file

@ -44,6 +44,7 @@ class FGNavRecord;
class SymbolInstance; class SymbolInstance;
class SymbolDef; class SymbolDef;
class SymbolRule;
namespace flightgear namespace flightgear
{ {
@ -51,6 +52,7 @@ namespace flightgear
} }
typedef std::set<std::string> string_set; typedef std::set<std::string> string_set;
typedef std::vector<SymbolRule*> SymbolRuleVector;
typedef std::vector<SymbolDef*> SymbolDefVector; typedef std::vector<SymbolDef*> SymbolDefVector;
class NavDisplay : public SGSubsystem class NavDisplay : public SGSubsystem
@ -95,6 +97,11 @@ protected:
SGPropertyNode *getInstrumentNode(const char *name, DefaultType value); SGPropertyNode *getInstrumentNode(const char *name, DefaultType value);
private: private:
friend class SymbolRule;
friend class SymbolDef;
void addRule(SymbolRule*);
void addSymbolsToScene(); void addSymbolsToScene();
void addSymbolToScene(SymbolInstance* sym); void addSymbolToScene(SymbolInstance* sym);
void limitDisplayedSymbols(); void limitDisplayedSymbols();
@ -112,7 +119,7 @@ private:
bool anyRuleForType(const std::string& type) const; 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, SymbolDefVector& rules); void findRules(const std::string& type, const string_set& states, SymbolRuleVector& rules);
SymbolInstance* addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars); SymbolInstance* addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars);
void addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec4& color); void addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec4& color);
@ -171,7 +178,8 @@ private:
double _rangeNm; double _rangeNm;
SGPropertyNode_ptr _rangeNode; SGPropertyNode_ptr _rangeNode;
SymbolDefVector _rules; SymbolDefVector _definitions;
SymbolRuleVector _rules;
FGNavRecord* _nav1Station; FGNavRecord* _nav1Station;
FGNavRecord* _nav2Station; FGNavRecord* _nav2Station;
std::vector<SymbolInstance*> _symbols; std::vector<SymbolInstance*> _symbols;