Allow distinct rule and symbol definitions for navDisplays.
This commit is contained in:
parent
0b6579e0e4
commit
96cd6018f9
2 changed files with 153 additions and 70 deletions
|
@ -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,21 +182,26 @@ 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;
|
||||||
while (node->hasChild("state", n)) {
|
while (node->hasChild("state", n)) {
|
||||||
string m = node->getChild("state", n++)->getStringValue();
|
string m = node->getChild("state", n++)->getStringValue();
|
||||||
|
@ -205,19 +212,79 @@ public:
|
||||||
}
|
}
|
||||||
} // of matches parsing
|
} // of matches parsing
|
||||||
|
|
||||||
if (node->hasChild("width")) {
|
return true;
|
||||||
float w = node->getFloatValue("width");
|
}
|
||||||
float h = node->getFloatValue("height", w);
|
|
||||||
xy0.x() = -w * 0.5;
|
void setDefinition(SymbolDef* d)
|
||||||
xy0.y() = -h * 0.5;
|
{
|
||||||
xy1.x() = w * 0.5;
|
definition = d;
|
||||||
xy1.y() = h * 0.5;
|
}
|
||||||
} else {
|
|
||||||
xy0.x() = node->getFloatValue("x0", 0.0);
|
SymbolDef* getDefinition() const
|
||||||
xy0.y() = node->getFloatValue("y0", 0.0);
|
{ return definition; }
|
||||||
xy1.x() = node->getFloatValue("x1", 5);
|
|
||||||
xy1.y() = node->getFloatValue("y1", 5);
|
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")) {
|
||||||
|
float w = node->getFloatValue("width");
|
||||||
|
float h = node->getFloatValue("height", w);
|
||||||
|
xy0.x() = -w * 0.5;
|
||||||
|
xy0.y() = -h * 0.5;
|
||||||
|
xy1.x() = w * 0.5;
|
||||||
|
xy1.y() = h * 0.5;
|
||||||
|
} else {
|
||||||
|
xy0.x() = node->getFloatValue("x0", 0.0);
|
||||||
|
xy0.y() = node->getFloatValue("y0", 0.0);
|
||||||
|
xy1.x() = node->getFloatValue("x1", 5);
|
||||||
|
xy1.y() = node->getFloatValue("y1", 5);
|
||||||
|
}
|
||||||
|
|
||||||
double texSize = node->getFloatValue("texture-size", owner->textureSize());
|
double texSize = node->getFloatValue("texture-size", owner->textureSize());
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue