1
0
Fork 0

Support for multiple data dirs.

This commit is contained in:
James Turner 2013-06-27 09:37:53 +01:00
parent fda64d840e
commit 33425c671d
6 changed files with 390 additions and 295 deletions

View file

@ -28,6 +28,7 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <boost/foreach.hpp>
#include <string> #include <string>
#include <osg/ref_ptr> #include <osg/ref_ptr>
@ -350,9 +351,11 @@ bool FGAIBase::init(bool search_in_AI_path)
osg::ref_ptr<osgDB::ReaderWriter::Options> osg::ref_ptr<osgDB::ReaderWriter::Options>
opt(osg::clone(osgDB::Registry::instance()->getOptions(), osg::CopyOp::SHALLOW_COPY)); opt(osg::clone(osgDB::Registry::instance()->getOptions(), osg::CopyOp::SHALLOW_COPY));
SGPath ai_path(globals->get_fg_root(), "AI"); osgDB::FilePathList& paths(opt->getDatabasePathList());
opt->setDatabasePath(ai_path.str()); paths.clear();
BOOST_FOREACH(SGPath p, globals->get_data_paths("AI")) {
paths.push_back(p.str());
}
f = osgDB::findDataFile(model_path, opt.get()); f = osgDB::findDataFile(model_path, opt.get());
} }

View file

@ -252,6 +252,54 @@ void FGGlobals::set_fg_home (const std::string &home) {
fg_home = tmp.realpath(); fg_home = tmp.realpath();
} }
PathList FGGlobals::get_data_paths() const
{
PathList r(additional_data_paths);
r.push_back(SGPath(fg_root));
return r;
}
PathList FGGlobals::get_data_paths(const std::string& suffix) const
{
PathList r;
BOOST_FOREACH(SGPath p, get_data_paths()) {
p.append(suffix);
if (p.exists()) {
r.push_back(p);
}
}
return r;
}
void FGGlobals::append_data_path(const SGPath& path)
{
if (!path.exists()) {
SG_LOG(SG_GENERAL, SG_WARN, "adding non-existant data path:" << path);
}
additional_data_paths.push_back(path);
}
SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
{
BOOST_FOREACH(SGPath p, additional_data_paths) {
p.append(pathSuffix);
if (p.exists()) {
return p;
}
}
SGPath rootPath(fg_root);
rootPath.append(pathSuffix);
if (rootPath.exists()) {
return rootPath;
}
SG_LOG(SG_GENERAL, SG_WARN, "dir not found in any data path:" << pathSuffix);
return SGPath();
}
void FGGlobals::append_fg_scenery (const std::string &paths) void FGGlobals::append_fg_scenery (const std::string &paths)
{ {
// fg_scenery.clear(); // fg_scenery.clear();

View file

@ -33,6 +33,7 @@
#include <string> #include <string>
typedef std::vector<std::string> string_list; typedef std::vector<std::string> string_list;
typedef std::vector<SGPath> PathList;
// Forward declarations // Forward declarations
@ -93,6 +94,11 @@ private:
// Root of FlightGear data tree // Root of FlightGear data tree
std::string fg_root; std::string fg_root;
/**
* locations to search for (non-scenery) data.
*/
PathList additional_data_paths;
// Users home directory for data // Users home directory for data
std::string fg_home; std::string fg_home;
@ -178,6 +184,26 @@ public:
inline const std::string &get_fg_root () const { return fg_root; } inline const std::string &get_fg_root () const { return fg_root; }
void set_fg_root (const std::string &root); void set_fg_root (const std::string &root);
/**
* Get list of data locations. fg_root is always the final item in the
* result.
*/
PathList get_data_paths() const;
/**
* Get data locations which contain the file path suffix. Eg pass ing
* 'AI/Traffic' to get all data paths which define <path>/AI/Traffic subdir
*/
PathList get_data_paths(const std::string& suffix) const;
void append_data_path(const SGPath& path);
/**
* Given a path suffix (eg 'Textures' or 'AI/Traffic'), find the
* first data directory which defines it.
*/
SGPath find_data_dir(const std::string& pathSuffix) const;
inline const std::string &get_fg_home () const { return fg_home; } inline const std::string &get_fg_home () const { return fg_home; }
void set_fg_home (const std::string &home); void set_fg_home (const std::string &home);

View file

@ -596,6 +596,16 @@ static naRef f_resolveDataPath(naContext c, naRef me, int argc, naRef* args)
return naStr_fromdata(naNewString(c), const_cast<char*>(pdata), strlen(pdata)); return naStr_fromdata(naNewString(c), const_cast<char*>(pdata), strlen(pdata));
} }
static naRef f_findDataDir(naContext c, naRef me, int argc, naRef* args)
{
if(argc != 1 || !naIsString(args[0]))
naRuntimeError(c, "bad arguments to findDataDir()");
SGPath p = globals->find_data_dir(naStr_data(args[0]));
const char* pdata = p.c_str();
return naStr_fromdata(naNewString(c), const_cast<char*>(pdata), strlen(pdata));
}
class NasalCommand : public SGCommandMgr::Command class NasalCommand : public SGCommandMgr::Command
{ {
public: public:
@ -724,6 +734,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
{ "abort", f_abort }, { "abort", f_abort },
{ "directory", f_directory }, { "directory", f_directory },
{ "resolvepath", f_resolveDataPath }, { "resolvepath", f_resolveDataPath },
{ "finddata", f_findDataDir },
{ "parsexml", f_parsexml }, { "parsexml", f_parsexml },
{ "systime", f_systime }, { "systime", f_systime },
{ 0, 0 } { 0, 0 }

View file

@ -76,13 +76,19 @@ using std::endl;
/** /**
* Thread encapsulating parsing the traffic schedules. * Thread encapsulating parsing the traffic schedules.
*/ */
class ScheduleParseThread : public SGThread class ScheduleParseThread : public SGThread, public XMLVisitor
{ {
public: public:
ScheduleParseThread(FGTrafficManager* traffic) : ScheduleParseThread(FGTrafficManager* traffic) :
_trafficManager(traffic), _trafficManager(traffic),
_isFinished(false), _isFinished(false),
_cancelThread(false) _cancelThread(false),
cruiseAlt(0),
score(0),
acCounter(0),
radius(0),
offset(0),
heavy(false)
{ {
} }
@ -100,9 +106,9 @@ public:
} }
} }
void setTrafficDir(const SGPath& trafficDirPath) void setTrafficDirs(const PathList& dirs)
{ {
_trafficDirPath = trafficDirPath; _trafficDirPaths = dirs;
} }
bool isFinished() const bool isFinished() const
@ -113,35 +119,289 @@ public:
virtual void run() virtual void run()
{ {
SGTimeStamp st; BOOST_FOREACH(SGPath p, _trafficDirPaths) {
st.stamp(); parseTrafficDir(p);
if (_cancelThread) {
simgear::Dir trafficDir(_trafficDirPath); return;
simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT); }
BOOST_FOREACH(SGPath p, d) {
simgear::Dir d2(p);
simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
BOOST_FOREACH(SGPath xml, trafficFiles) {
_trafficManager->parseSchedule(xml);
if (_cancelThread) {
return;
}
} }
} // of sub-directories in AI/Traffic iteration
// _trafficManager->parseSchedules(schedulesToRead);
SG_LOG(SG_AI, SG_INFO, "parsing traffic schedules took:" << st.elapsedMSec() << "msec");
SGGuard<SGMutex> g(_lock); SGGuard<SGMutex> g(_lock);
_isFinished = true; _isFinished = true;
} }
void startXML()
{
//cout << "Start XML" << endl;
requiredAircraft = "";
homePort = "";
}
void endXML()
{
//cout << "End XML" << endl;
}
void startElement(const char *name,
const XMLAttributes & atts)
{
const char *attval;
//cout << "Start element " << name << endl;
//FGTrafficManager temp;
//for (int i = 0; i < atts.size(); i++)
// if (string(atts.getName(i)) == string("include"))
attval = atts.getValue("include");
if (attval != 0) {
//cout << "including " << attval << endl;
SGPath path = globals->get_fg_root();
path.append("/Traffic/");
path.append(attval);
readXML(path.str(), *this);
}
elementValueStack.push_back("");
// cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
}
void endElement(const char *name)
{
//cout << "End element " << name << endl;
const string & value = elementValueStack.back();
if (!strcmp(name, "model"))
mdl = value;
else if (!strcmp(name, "livery"))
livery = value;
else if (!strcmp(name, "home-port"))
homePort = value;
else if (!strcmp(name, "registration"))
registration = value;
else if (!strcmp(name, "airline"))
airline = value;
else if (!strcmp(name, "actype"))
acType = value;
else if (!strcmp(name, "required-aircraft"))
requiredAircraft = value;
else if (!strcmp(name, "flighttype"))
flighttype = value;
else if (!strcmp(name, "radius"))
radius = atoi(value.c_str());
else if (!strcmp(name, "offset"))
offset = atoi(value.c_str());
else if (!strcmp(name, "performance-class"))
m_class = value;
else if (!strcmp(name, "heavy")) {
if (value == string("true"))
heavy = true;
else
heavy = false;
} else if (!strcmp(name, "callsign"))
callsign = value;
else if (!strcmp(name, "fltrules"))
fltrules = value;
else if (!strcmp(name, "port"))
port = value;
else if (!strcmp(name, "time"))
timeString = value;
else if (!strcmp(name, "departure")) {
departurePort = port;
departureTime = timeString;
} else if (!strcmp(name, "cruise-alt"))
cruiseAlt = atoi(value.c_str());
else if (!strcmp(name, "arrival")) {
arrivalPort = port;
arrivalTime = timeString;
} else if (!strcmp(name, "repeat"))
repeat = value;
else if (!strcmp(name, "flight")) {
// We have loaded and parsed all the information belonging to this flight
// so we temporarily store it.
//cerr << "Pusing back flight " << callsign << endl;
//cerr << callsign << " " << fltrules << " "<< departurePort << " " << arrivalPort << " "
// << cruiseAlt << " " << departureTime<< " "<< arrivalTime << " " << repeat << endl;
//Prioritize aircraft
string apt = fgGetString("/sim/presets/airport-id");
//cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
//if (departurePort == apt) score++;
//flights.push_back(new FGScheduledFlight(callsign,
// fltrules,
// departurePort,
// arrivalPort,
// cruiseAlt,
// departureTime,
// arrivalTime,
// repeat));
if (requiredAircraft == "") {
char buffer[16];
snprintf(buffer, 16, "%d", acCounter);
requiredAircraft = buffer;
}
SG_LOG(SG_AI, SG_DEBUG, "Adding flight: " << callsign << " "
<< fltrules << " "
<< departurePort << " "
<< arrivalPort << " "
<< cruiseAlt << " "
<< departureTime << " "
<< arrivalTime << " " << repeat << " " << requiredAircraft);
// For database maintainance purposes, it may be convenient to
//
if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
SG_LOG(SG_AI, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
<< fltrules << ","
<< departurePort << ","
<< arrivalPort << ","
<< cruiseAlt << ","
<< departureTime << ","
<< arrivalTime << "," << repeat << "," << requiredAircraft);
}
_trafficManager->flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
fltrules,
departurePort,
arrivalPort,
cruiseAlt,
departureTime,
arrivalTime,
repeat,
requiredAircraft));
requiredAircraft = "";
} else if (!strcmp(name, "aircraft")) {
endAircraft();
}
elementValueStack.pop_back();
}
void data(const char *s, int len)
{
string token = string(s, len);
//cout << "Character data " << string(s,len) << endl;
elementValueStack.back() += token;
}
void pi(const char *target, const char *data)
{
//cout << "Processing instruction " << target << ' ' << data << endl;
}
void warning(const char *message, int line, int column)
{
SG_LOG(SG_IO, SG_WARN,
"Warning: " << message << " (" << line << ',' << column << ')');
}
void error(const char *message, int line, int column)
{
SG_LOG(SG_IO, SG_ALERT,
"Error: " << message << " (" << line << ',' << column << ')');
}
private: private:
void endAircraft()
{
string isHeavy = heavy ? "true" : "false";
if (missingModels.find(mdl) != missingModels.end()) {
// don't stat() or warn again
requiredAircraft = homePort = "";
return;
}
if (!FGAISchedule::validModelPath(mdl)) {
missingModels.insert(mdl);
SG_LOG(SG_AI, SG_WARN, "TrafficMgr: Missing model path:" << mdl);
requiredAircraft = homePort = "";
return;
}
int proportion =
(int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
int randval = rand() & 100;
if (randval > proportion) {
requiredAircraft = homePort = "";
return;
}
if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
SG_LOG(SG_AI, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft
<< "," << acType << "," << livery << ","
<< airline << "," << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
}
if (requiredAircraft == "") {
char buffer[16];
snprintf(buffer, 16, "%d", acCounter);
requiredAircraft = buffer;
}
if (homePort == "") {
homePort = departurePort;
}
// caution, modifying the scheduled aircraft strucutre from the
// 'wrong' thread. This is safe becuase FGTrafficManager won't touch
// the structure while we exist.
_trafficManager->scheduledAircraft.push_back(new FGAISchedule(mdl,
livery,
homePort,
registration,
requiredAircraft,
heavy,
acType,
airline,
m_class,
flighttype,
radius, offset));
acCounter++;
requiredAircraft = "";
homePort = "";
score = 0;
}
void parseTrafficDir(const SGPath& path)
{
SGTimeStamp st;
st.stamp();
simgear::Dir trafficDir(path);
simgear::PathList d = trafficDir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
BOOST_FOREACH(SGPath p, d) {
simgear::Dir d2(p);
simgear::PathList trafficFiles = d2.children(simgear::Dir::TYPE_FILE, ".xml");
BOOST_FOREACH(SGPath xml, trafficFiles) {
readXML(xml.str(), *this);
if (_cancelThread) {
return;
}
}
} // of sub-directories iteration
SG_LOG(SG_AI, SG_INFO, "parsing traffic schedules took:" << st.elapsedMSec() << "msec");
}
FGTrafficManager* _trafficManager; FGTrafficManager* _trafficManager;
mutable SGMutex _lock; mutable SGMutex _lock;
bool _isFinished; bool _isFinished;
bool _cancelThread; bool _cancelThread;
SGPath _trafficDirPath; PathList _trafficDirPaths;
// parser state
string_list elementValueStack;
// record model paths which are missing, to avoid duplicate
// warnings when parsing traffic schedules.
std::set<std::string> missingModels;
std::string mdl, livery, registration, callsign, fltrules,
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
repeat, acType, airline, m_class, flighttype, requiredAircraft, homePort;
int cruiseAlt;
int score, acCounter;
double radius, offset;
bool heavy;
}; };
/****************************************************************************** /******************************************************************************
@ -151,12 +411,6 @@ FGTrafficManager::FGTrafficManager() :
inited(false), inited(false),
doingInit(false), doingInit(false),
waitingMetarTime(0.0), waitingMetarTime(0.0),
cruiseAlt(0),
score(0),
acCounter(0),
radius(0),
offset(0),
heavy(false),
enabled("/sim/traffic-manager/enabled"), enabled("/sim/traffic-manager/enabled"),
aiEnabled("/sim/ai/enabled"), aiEnabled("/sim/ai/enabled"),
realWxEnabled("/environment/realwx/enabled"), realWxEnabled("/environment/realwx/enabled"),
@ -224,14 +478,6 @@ void FGTrafficManager::shutdown()
inited = false; inited = false;
} }
/// caution - this is run on the helper thread to improve startup
/// responsiveness - do not access properties or global state from
/// here, since there's no locking protection at all
void FGTrafficManager::parseSchedule(const SGPath& path)
{
readXML(path.str(), *this);
}
void FGTrafficManager::init() void FGTrafficManager::init()
{ {
if (!enabled) { if (!enabled) {
@ -240,9 +486,15 @@ void FGTrafficManager::init()
assert(!doingInit); assert(!doingInit);
doingInit = true; doingInit = true;
if (string(fgGetString("/sim/traffic-manager/datafile")).empty()) { if (string(fgGetString("/sim/traffic-manager/datafile")).empty()) {
PathList dirs = globals->get_data_paths("AI/Traffic");
if (dirs.empty()) {
doingInit = false;
return;
}
scheduleParser.reset(new ScheduleParseThread(this)); scheduleParser.reset(new ScheduleParseThread(this));
scheduleParser->setTrafficDir(SGPath(globals->get_fg_root(), "AI/Traffic")); scheduleParser->setTrafficDirs(dirs);
scheduleParser->start(); scheduleParser->start();
} else { } else {
fgSetBool("/sim/traffic-manager/heuristics", false); fgSetBool("/sim/traffic-manager/heuristics", false);
@ -250,7 +502,10 @@ void FGTrafficManager::init()
string ext = path.extension(); string ext = path.extension();
if (path.extension() == "xml") { if (path.extension() == "xml") {
if (path.exists()) { if (path.exists()) {
readXML(path.str(), *this); // use a SchedulerParser to parse, but run it in this thread,
// i.e don't start it
ScheduleParseThread parser(this);
readXML(path.str(), parser);
} }
} else if (path.extension() == "conf") { } else if (path.extension() == "conf") {
if (path.exists()) { if (path.exists()) {
@ -597,225 +852,3 @@ void FGTrafficManager::Tokenize(const string& str,
} }
void FGTrafficManager::startXML()
{
//cout << "Start XML" << endl;
requiredAircraft = "";
homePort = "";
}
void FGTrafficManager::endXML()
{
//cout << "End XML" << endl;
}
void FGTrafficManager::startElement(const char *name,
const XMLAttributes & atts)
{
const char *attval;
//cout << "Start element " << name << endl;
//FGTrafficManager temp;
//for (int i = 0; i < atts.size(); i++)
// if (string(atts.getName(i)) == string("include"))
attval = atts.getValue("include");
if (attval != 0) {
//cout << "including " << attval << endl;
SGPath path = globals->get_fg_root();
path.append("/Traffic/");
path.append(attval);
readXML(path.str(), *this);
}
elementValueStack.push_back("");
// cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
}
void FGTrafficManager::endElement(const char *name)
{
//cout << "End element " << name << endl;
const string & value = elementValueStack.back();
if (!strcmp(name, "model"))
mdl = value;
else if (!strcmp(name, "livery"))
livery = value;
else if (!strcmp(name, "home-port"))
homePort = value;
else if (!strcmp(name, "registration"))
registration = value;
else if (!strcmp(name, "airline"))
airline = value;
else if (!strcmp(name, "actype"))
acType = value;
else if (!strcmp(name, "required-aircraft"))
requiredAircraft = value;
else if (!strcmp(name, "flighttype"))
flighttype = value;
else if (!strcmp(name, "radius"))
radius = atoi(value.c_str());
else if (!strcmp(name, "offset"))
offset = atoi(value.c_str());
else if (!strcmp(name, "performance-class"))
m_class = value;
else if (!strcmp(name, "heavy")) {
if (value == string("true"))
heavy = true;
else
heavy = false;
} else if (!strcmp(name, "callsign"))
callsign = value;
else if (!strcmp(name, "fltrules"))
fltrules = value;
else if (!strcmp(name, "port"))
port = value;
else if (!strcmp(name, "time"))
timeString = value;
else if (!strcmp(name, "departure")) {
departurePort = port;
departureTime = timeString;
} else if (!strcmp(name, "cruise-alt"))
cruiseAlt = atoi(value.c_str());
else if (!strcmp(name, "arrival")) {
arrivalPort = port;
arrivalTime = timeString;
} else if (!strcmp(name, "repeat"))
repeat = value;
else if (!strcmp(name, "flight")) {
// We have loaded and parsed all the information belonging to this flight
// so we temporarily store it.
//cerr << "Pusing back flight " << callsign << endl;
//cerr << callsign << " " << fltrules << " "<< departurePort << " " << arrivalPort << " "
// << cruiseAlt << " " << departureTime<< " "<< arrivalTime << " " << repeat << endl;
//Prioritize aircraft
string apt = fgGetString("/sim/presets/airport-id");
//cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
//if (departurePort == apt) score++;
//flights.push_back(new FGScheduledFlight(callsign,
// fltrules,
// departurePort,
// arrivalPort,
// cruiseAlt,
// departureTime,
// arrivalTime,
// repeat));
if (requiredAircraft == "") {
char buffer[16];
snprintf(buffer, 16, "%d", acCounter);
requiredAircraft = buffer;
}
SG_LOG(SG_AI, SG_DEBUG, "Adding flight: " << callsign << " "
<< fltrules << " "
<< departurePort << " "
<< arrivalPort << " "
<< cruiseAlt << " "
<< departureTime << " "
<< arrivalTime << " " << repeat << " " << requiredAircraft);
// For database maintainance purposes, it may be convenient to
//
if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
SG_LOG(SG_AI, SG_ALERT, "Traffic Dump FLIGHT," << callsign << ","
<< fltrules << ","
<< departurePort << ","
<< arrivalPort << ","
<< cruiseAlt << ","
<< departureTime << ","
<< arrivalTime << "," << repeat << "," << requiredAircraft);
}
flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
fltrules,
departurePort,
arrivalPort,
cruiseAlt,
departureTime,
arrivalTime,
repeat,
requiredAircraft));
requiredAircraft = "";
} else if (!strcmp(name, "aircraft")) {
endAircraft();
}
elementValueStack.pop_back();
}
void FGTrafficManager::endAircraft()
{
string isHeavy = heavy ? "true" : "false";
if (missingModels.find(mdl) != missingModels.end()) {
// don't stat() or warn again
requiredAircraft = homePort = "";
return;
}
if (!FGAISchedule::validModelPath(mdl)) {
missingModels.insert(mdl);
SG_LOG(SG_AI, SG_WARN, "TrafficMgr: Missing model path:" << mdl);
requiredAircraft = homePort = "";
return;
}
int proportion =
(int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
int randval = rand() & 100;
if (randval > proportion) {
requiredAircraft = homePort = "";
return;
}
if (fgGetBool("/sim/traffic-manager/dumpdata") == true) {
SG_LOG(SG_AI, SG_ALERT, "Traffic Dump AC," << homePort << "," << registration << "," << requiredAircraft
<< "," << acType << "," << livery << ","
<< airline << "," << m_class << "," << offset << "," << radius << "," << flighttype << "," << isHeavy << "," << mdl);
}
if (requiredAircraft == "") {
char buffer[16];
snprintf(buffer, 16, "%d", acCounter);
requiredAircraft = buffer;
}
if (homePort == "") {
homePort = departurePort;
}
scheduledAircraft.push_back(new FGAISchedule(mdl,
livery,
homePort,
registration,
requiredAircraft,
heavy,
acType,
airline,
m_class,
flighttype,
radius, offset));
acCounter++;
requiredAircraft = "";
homePort = "";
score = 0;
}
void FGTrafficManager::data(const char *s, int len)
{
string token = string(s, len);
//cout << "Character data " << string(s,len) << endl;
elementValueStack.back() += token;
}
void FGTrafficManager::pi(const char *target, const char *data)
{
//cout << "Processing instruction " << target << ' ' << data << endl;
}
void FGTrafficManager::warning(const char *message, int line, int column)
{
SG_LOG(SG_IO, SG_WARN,
"Warning: " << message << " (" << line << ',' << column << ')');
}
void FGTrafficManager::error(const char *message, int line, int column)
{
SG_LOG(SG_IO, SG_ALERT,
"Error: " << message << " (" << line << ',' << column << ')');
}

View file

@ -51,9 +51,7 @@
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/propertyObject.hxx> #include <simgear/props/propertyObject.hxx>
#include <simgear/xml/easyxml.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sg_dir.hxx>
#include "SchedFlight.hxx" #include "SchedFlight.hxx"
#include "Schedule.hxx" #include "Schedule.hxx"
@ -77,7 +75,7 @@ typedef HeuristicMap::iterator HeuristicMapIterator;
class ScheduleParseThread; class ScheduleParseThread;
class FGTrafficManager : public SGSubsystem, public XMLVisitor class FGTrafficManager : public SGSubsystem
{ {
private: private:
bool inited; bool inited;
@ -87,24 +85,11 @@ private:
ScheduleVector scheduledAircraft; ScheduleVector scheduledAircraft;
ScheduleVectorIterator currAircraft, currAircraftClosest; ScheduleVectorIterator currAircraft, currAircraftClosest;
vector<string> elementValueStack;
// record model paths which are missing, to avoid duplicate
// warnings when parsing traffic schedules.
std::set<std::string> missingModels;
std::string mdl, livery, registration, callsign, fltrules,
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
repeat, acType, airline, m_class, flighttype, requiredAircraft, homePort;
int cruiseAlt;
int score, acCounter;
double radius, offset;
bool heavy;
FGScheduledFlightMap flights; FGScheduledFlightMap flights;
void readTimeTableFromFile(SGPath infilename); void readTimeTableFromFile(SGPath infilename);
void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " "); void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = " ");
simgear::PropertyObject<bool> enabled, aiEnabled, realWxEnabled, metarValid; simgear::PropertyObject<bool> enabled, aiEnabled, realWxEnabled, metarValid;
@ -129,20 +114,9 @@ public:
void init(); void init();
void update(double time); void update(double time);
FGScheduledFlightVecIterator getFirstFlight(const string &ref) { return flights[ref].begin(); } FGScheduledFlightVecIterator getFirstFlight(const std::string &ref) { return flights[ref].begin(); }
FGScheduledFlightVecIterator getLastFlight(const string &ref) { return flights[ref].end(); } FGScheduledFlightVecIterator getLastFlight(const std::string &ref) { return flights[ref].end(); }
void endAircraft();
// Some overloaded virtual XMLVisitor members
virtual void startXML ();
virtual void endXML ();
virtual void startElement (const char * name, const XMLAttributes &atts);
virtual void endElement (const char * name);
virtual void data (const char * s, int len);
virtual void pi (const char * target, const char * data);
virtual void warning (const char * message, int line, int column);
virtual void error (const char * message, int line, int column);
}; };
#endif #endif