GPSs uses FlightPlans directly.
This commit is contained in:
parent
a0cf59d8af
commit
e89df85817
13 changed files with 331 additions and 943 deletions
|
@ -215,13 +215,17 @@ FGRouteMgr::FGRouteMgr() :
|
|||
input->setStringValue("");
|
||||
input->addChangeListener(listener);
|
||||
|
||||
SGCommandMgr::instance()->addCommand("load-flightplan", commandLoadFlightPlan);
|
||||
SGCommandMgr::instance()->addCommand("save-flightplan", commandSaveFlightPlan);
|
||||
SGCommandMgr::instance()->addCommand("activate-flightplan", commandActivateFlightPlan);
|
||||
SGCommandMgr::instance()->addCommand("clear-flightplan", commandClearFlightPlan);
|
||||
SGCommandMgr::instance()->addCommand("set-active-waypt", commandSetActiveWaypt);
|
||||
SGCommandMgr::instance()->addCommand("insert-waypt", commandInsertWaypt);
|
||||
SGCommandMgr::instance()->addCommand("delete-waypt", commandDeleteWaypt);
|
||||
SGCommandMgr* cmdMgr = SGCommandMgr::instance();
|
||||
cmdMgr->addCommand("define-user-waypoint", this, &FGRouteMgr::commandDefineUserWaypoint);
|
||||
cmdMgr->addCommand("delete-user-waypoint", this, &FGRouteMgr::commandDeleteUserWaypoint);
|
||||
|
||||
cmdMgr->addCommand("load-flightplan", commandLoadFlightPlan);
|
||||
cmdMgr->addCommand("save-flightplan", commandSaveFlightPlan);
|
||||
cmdMgr->addCommand("activate-flightplan", commandActivateFlightPlan);
|
||||
cmdMgr->addCommand("clear-flightplan", commandClearFlightPlan);
|
||||
cmdMgr->addCommand("set-active-waypt", commandSetActiveWaypt);
|
||||
cmdMgr->addCommand("insert-waypt", commandInsertWaypt);
|
||||
cmdMgr->addCommand("delete-waypt", commandDeleteWaypt);
|
||||
}
|
||||
|
||||
|
||||
|
@ -229,6 +233,10 @@ FGRouteMgr::~FGRouteMgr()
|
|||
{
|
||||
input->removeChangeListener(listener);
|
||||
delete listener;
|
||||
|
||||
SGCommandMgr* cmdMgr = SGCommandMgr::instance();
|
||||
//cmdMgr->removeCommand("define-user-waypoint");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -306,14 +314,12 @@ void FGRouteMgr::init() {
|
|||
airborne->setBoolValue(false);
|
||||
|
||||
_edited = fgGetNode(RM "signals/edited", true);
|
||||
_finished = fgGetNode(RM "signals/finished", true);
|
||||
_flightplanChanged = fgGetNode(RM "signals/flightplan-changed", true);
|
||||
|
||||
_currentWpt = fgGetNode(RM "current-wp", true);
|
||||
_currentWpt->tie(SGRawValueMethods<FGRouteMgr, int>
|
||||
(*this, &FGRouteMgr::currentIndex, &FGRouteMgr::jumpToIndex));
|
||||
|
||||
// temporary distance / eta calculations, for backward-compatability
|
||||
wp0 = fgGetNode(RM "wp", 0, true);
|
||||
wp0->getChild("id", 0, true);
|
||||
wp0->getChild("dist", 0, true);
|
||||
|
@ -454,10 +460,6 @@ void FGRouteMgr::update( double dt )
|
|||
return;
|
||||
}
|
||||
|
||||
if (checkFinished()) {
|
||||
endOfRoute();
|
||||
}
|
||||
|
||||
// basic course/distance information
|
||||
SGGeod currentPos = globals->get_aircraft_position();
|
||||
|
||||
|
@ -590,11 +592,6 @@ void FGRouteMgr::waypointsChanged()
|
|||
{
|
||||
update_mirror();
|
||||
_edited->fireValueChanged();
|
||||
|
||||
// removing waypoints, deactivate if we hit the end.
|
||||
if (currentIndex() >= numLegs()) {
|
||||
endOfRoute();
|
||||
}
|
||||
}
|
||||
|
||||
// mirror internal route to the property system for inspection by other subsystems
|
||||
|
@ -713,63 +710,10 @@ void FGRouteMgr::InputListener::valueChanged(SGPropertyNode *prop)
|
|||
r++;
|
||||
if (*r)
|
||||
mgr->flightPlan()->insertWayptAtIndex(mgr->waypointFromString(r), pos);
|
||||
} else if (!strcmp(s, "@POSINIT")) {
|
||||
mgr->initAtPosition();
|
||||
} else
|
||||
mgr->flightPlan()->insertWayptAtIndex(mgr->waypointFromString(s), -1);
|
||||
}
|
||||
|
||||
void FGRouteMgr::initAtPosition()
|
||||
{
|
||||
if (isRouteActive()) {
|
||||
return; // don't mess with the active route
|
||||
}
|
||||
|
||||
if (haveUserWaypoints()) {
|
||||
// user has already defined, loaded or entered a route, again
|
||||
// don't interfere with it
|
||||
return;
|
||||
}
|
||||
|
||||
if (airborne->getBoolValue()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: airborne, clearing departure info");
|
||||
_plan->setDeparture((FGAirport*) NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// on the ground
|
||||
SGGeod pos = globals->get_aircraft_position();
|
||||
if (!_plan->departureAirport()) {
|
||||
_plan->setDeparture(FGAirport::findClosest(pos, 20.0));
|
||||
if (!_plan->departureAirport()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: couldn't find an airport within 20nm");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string rwy = departure->getStringValue("runway");
|
||||
FGRunway* r = NULL;
|
||||
if (!rwy.empty()) {
|
||||
r = _plan->departureAirport()->getRunwayByIdent(rwy);
|
||||
} else {
|
||||
r = _plan->departureAirport()->findBestRunwayForPos(pos);
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
return;
|
||||
}
|
||||
|
||||
_plan->setDeparture(r);
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "initAtPosition: starting at "
|
||||
<< _plan->departureAirport()->ident() << " on runway " << r->ident());
|
||||
}
|
||||
|
||||
bool FGRouteMgr::haveUserWaypoints() const
|
||||
{
|
||||
// FIXME
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FGRouteMgr::activate()
|
||||
{
|
||||
if (!_plan) {
|
||||
|
@ -798,52 +742,6 @@ void FGRouteMgr::deactivate()
|
|||
active->setBoolValue(false);
|
||||
}
|
||||
|
||||
void FGRouteMgr::sequence()
|
||||
{
|
||||
if (!_plan || !active->getBoolValue()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_ALERT, "trying to sequence waypoints with no active route");
|
||||
return;
|
||||
}
|
||||
|
||||
int nextIndex = _plan->currentIndex() + 1;
|
||||
if (nextIndex >= _plan->numLegs()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "sequenced on final leg, deactivating route");
|
||||
endOfRoute();
|
||||
return;
|
||||
}
|
||||
|
||||
_plan->setCurrentIndex(nextIndex);
|
||||
}
|
||||
|
||||
void FGRouteMgr::endOfRoute()
|
||||
{
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "reached end of active route");
|
||||
_finished->fireValueChanged();
|
||||
active->setBoolValue(false);
|
||||
}
|
||||
|
||||
bool FGRouteMgr::checkFinished()
|
||||
{
|
||||
if (!_plan) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
// done if we're stopped on the destination runway
|
||||
if (_plan->currentLeg() &&
|
||||
(_plan->currentLeg()->waypoint()->source() == _plan->destinationRunway()))
|
||||
{
|
||||
double gs = groundSpeed->getDoubleValue();
|
||||
done = weightOnWheels->getBoolValue() && (gs < 25);
|
||||
}
|
||||
|
||||
if (done) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_INFO, "checkFinished: on the ground on destination runway, we're done");
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
void FGRouteMgr::jumpToIndex(int index)
|
||||
{
|
||||
if (!_plan) {
|
||||
|
@ -1212,3 +1110,37 @@ SGPropertyNode_ptr FGRouteMgr::wayptNodeAtIndex(int index) const
|
|||
|
||||
return mirror->getChild("wp", index);
|
||||
}
|
||||
|
||||
bool FGRouteMgr::commandDefineUserWaypoint(const SGPropertyNode* arg)
|
||||
{
|
||||
std::string ident = arg->getStringValue("ident");
|
||||
if (ident.empty()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_WARN, "missing ident defining user waypoint");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for duplicate idents
|
||||
FGPositioned::TypeFilter f(FGPositioned::WAYPOINT);
|
||||
FGPositionedList dups = FGPositioned::findAllWithIdent(ident, &f);
|
||||
if (!dups.empty()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_WARN, "defineUserWaypoint: non-unique waypoint identifier:" << ident);
|
||||
return false;
|
||||
}
|
||||
|
||||
SGGeod pos(SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"),
|
||||
arg->getDoubleValue("latitude-deg")));
|
||||
FGPositioned::createUserWaypoint(ident, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FGRouteMgr::commandDeleteUserWaypoint(const SGPropertyNode* arg)
|
||||
{
|
||||
std::string ident = arg->getStringValue("ident");
|
||||
if (ident.empty()) {
|
||||
SG_LOG(SG_AUTOPILOT, SG_WARN, "missing ident deleting user waypoint");
|
||||
return false;
|
||||
}
|
||||
|
||||
return FGPositioned::deleteUserWaypoint(ident);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,11 +90,6 @@ public:
|
|||
*/
|
||||
void deactivate();
|
||||
|
||||
/**
|
||||
* Step to the next waypoint on the active route
|
||||
*/
|
||||
void sequence();
|
||||
|
||||
/**
|
||||
* Set the current waypoint to the specified index.
|
||||
*/
|
||||
|
@ -104,13 +99,11 @@ public:
|
|||
bool loadRoute(const SGPath& p);
|
||||
|
||||
flightgear::WayptRef waypointFromString(const std::string& target);
|
||||
|
||||
/**
|
||||
* Helper command to setup current airport/runway if necessary
|
||||
*/
|
||||
void initAtPosition();
|
||||
|
||||
private:
|
||||
bool commandDefineUserWaypoint(const SGPropertyNode* arg);
|
||||
bool commandDeleteUserWaypoint(const SGPropertyNode* arg);
|
||||
|
||||
flightgear::FlightPlan* _plan;
|
||||
|
||||
time_t _takeoffTime;
|
||||
|
@ -188,23 +181,6 @@ private:
|
|||
|
||||
virtual void currentWaypointChanged();
|
||||
|
||||
/**
|
||||
* Check if we've reached the final waypoint.
|
||||
* Returns true if we have.
|
||||
*/
|
||||
bool checkFinished();
|
||||
|
||||
/*
|
||||
* update state when we pass the final waypoint
|
||||
*/
|
||||
void endOfRoute();
|
||||
|
||||
/**
|
||||
* Predicate for helping the UI - test if at least one waypoint was
|
||||
* entered by the user (as opposed to being generated by the route-manager)
|
||||
*/
|
||||
bool haveUserWaypoints() const;
|
||||
|
||||
// tied getters and setters
|
||||
const char* getDepartureICAO() const;
|
||||
const char* getDepartureName() const;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,12 +15,9 @@
|
|||
#include <simgear/props/tiedpropertylist.hxx>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Navaids/FlightPlan.hxx>
|
||||
#include <Instrumentation/rnav_waypt_controller.hxx>
|
||||
|
||||
// forward decls
|
||||
class SGRoute;
|
||||
class FGRouteMgr;
|
||||
class GPSListener;
|
||||
|
||||
/**
|
||||
* Model a GPS radio.
|
||||
|
@ -57,10 +54,12 @@ class GPSListener;
|
|||
* /instrumentation/gps/true-bug-error-deg
|
||||
* /instrumentation/gps/magnetic-bug-error-deg
|
||||
*/
|
||||
class GPS : public SGSubsystem, public flightgear::RNAV
|
||||
class GPS : public SGSubsystem,
|
||||
public flightgear::RNAV,
|
||||
public flightgear::FlightPlan::Delegate
|
||||
{
|
||||
public:
|
||||
GPS (SGPropertyNode *node);
|
||||
GPS (SGPropertyNode *node, bool defaultGPSMode = false);
|
||||
GPS ();
|
||||
virtual ~GPS ();
|
||||
|
||||
|
@ -82,7 +81,6 @@ public:
|
|||
virtual double overflightArmDistanceM();
|
||||
|
||||
private:
|
||||
friend class GPSListener;
|
||||
friend class SearchFilter;
|
||||
|
||||
/**
|
||||
|
@ -142,9 +140,6 @@ private:
|
|||
// (in seconds)
|
||||
double _waypointAlertTime;
|
||||
|
||||
// minimum runway length to require when filtering
|
||||
double _minRunwayLengthFt;
|
||||
|
||||
// should we require a hard-surfaced runway when filtering?
|
||||
bool _requireHardSurface;
|
||||
|
||||
|
@ -172,15 +167,8 @@ private:
|
|||
void updateBasicData(double dt);
|
||||
|
||||
void updateTrackingBug();
|
||||
void updateReferenceNavaid(double dt);
|
||||
void referenceNavaidSet(const std::string& aNavaid);
|
||||
void updateRouteData();
|
||||
void driveAutopilot();
|
||||
|
||||
void routeActivated();
|
||||
void routeManagerSequenced();
|
||||
void routeEdited();
|
||||
void routeFinished();
|
||||
|
||||
void updateTurn();
|
||||
void updateOverflight();
|
||||
|
@ -195,49 +183,24 @@ private:
|
|||
/** Update one-shot things when WP1 / leg data change */
|
||||
void wp1Changed();
|
||||
|
||||
// scratch maintenance utilities
|
||||
void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
|
||||
void setScratchFromCachedSearchResult();
|
||||
void setScratchFromRouteWaypoint(int aIndex);
|
||||
|
||||
/** Add airport-specific information to a scratch result */
|
||||
void addAirportToScratch(FGAirport* aAirport);
|
||||
|
||||
void clearScratch();
|
||||
|
||||
/** Predicate, determine if the lon/lat position in the scratch is
|
||||
* valid or not. */
|
||||
bool isScratchPositionValid() const;
|
||||
|
||||
FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
|
||||
|
||||
/** Search kernel - called each time we step through a result */
|
||||
void performSearch();
|
||||
|
||||
// command handlers
|
||||
void selectLegMode();
|
||||
void selectOBSMode();
|
||||
void selectOBSMode(flightgear::Waypt* waypt);
|
||||
void directTo();
|
||||
void loadRouteWaypoint();
|
||||
void loadNearest();
|
||||
void search();
|
||||
void nextResult();
|
||||
void previousResult();
|
||||
void defineWaypoint();
|
||||
void insertWaypointAtIndex(int aIndex);
|
||||
void removeWaypointAtIndex(int aIndex);
|
||||
|
||||
// tied-property getter/setters
|
||||
void setCommand(const char* aCmd);
|
||||
const char* getCommand() const { return ""; }
|
||||
|
||||
const char* getMode() const { return _mode.c_str(); }
|
||||
|
||||
bool getScratchValid() const { return _scratchValid; }
|
||||
double getScratchDistance() const;
|
||||
double getScratchMagBearing() const;
|
||||
double getScratchTrueBearing() const;
|
||||
bool getScratchHasNext() const;
|
||||
|
||||
double getSelectedCourse() const { return _selectedCourse; }
|
||||
void setSelectedCourse(double crs);
|
||||
|
@ -254,9 +217,6 @@ private:
|
|||
double getGroundspeedKts() const { return _last_speed_kts; }
|
||||
double getVerticalSpeed() const { return _last_vertical_speed; }
|
||||
|
||||
//bool getLegMode() const { return _mode == "leg"; }
|
||||
//bool getObsMode() const { return _mode == "obs"; }
|
||||
|
||||
const char* getWP0Ident() const;
|
||||
const char* getWP0Name() const;
|
||||
|
||||
|
@ -293,6 +253,16 @@ private:
|
|||
void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
|
||||
const char* lonStr, const char* latStr, const char* altStr);
|
||||
|
||||
// FlightPlan::Delegate
|
||||
virtual void currentWaypointChanged();
|
||||
virtual void waypointsChanged();
|
||||
virtual void cleared();
|
||||
virtual void endOfFlightPlan();
|
||||
|
||||
void sequence();
|
||||
void routeManagerFlightPlanChanged(SGPropertyNode*);
|
||||
void routeActivated(SGPropertyNode*);
|
||||
|
||||
// members
|
||||
SGPropertyNode_ptr _gpsNode;
|
||||
SGPropertyNode_ptr _currentWayptNode;
|
||||
|
@ -308,22 +278,13 @@ private:
|
|||
SGPropertyNode_ptr _magnetic_bug_error_node;
|
||||
SGPropertyNode_ptr _eastWestVelocity;
|
||||
SGPropertyNode_ptr _northSouthVelocity;
|
||||
|
||||
SGPropertyNode_ptr _ref_navaid_id_node;
|
||||
SGPropertyNode_ptr _ref_navaid_bearing_node;
|
||||
SGPropertyNode_ptr _ref_navaid_distance_node;
|
||||
SGPropertyNode_ptr _ref_navaid_mag_bearing_node;
|
||||
SGPropertyNode_ptr _ref_navaid_frequency_node;
|
||||
SGPropertyNode_ptr _ref_navaid_name_node;
|
||||
|
||||
SGPropertyNode_ptr _route_active_node;
|
||||
|
||||
// SGPropertyNode_ptr _route_active_node;
|
||||
SGPropertyNode_ptr _route_current_wp_node;
|
||||
SGPropertyNode_ptr _routeDistanceNm;
|
||||
SGPropertyNode_ptr _routeETE;
|
||||
SGPropertyNode_ptr _routeEditedSignal;
|
||||
SGPropertyNode_ptr _routeFinishedSignal;
|
||||
SGPropertyNode_ptr _desiredCourseNode;
|
||||
|
||||
|
||||
double _selectedCourse;
|
||||
double _desiredCourse;
|
||||
|
||||
|
@ -336,15 +297,17 @@ private:
|
|||
double _lastEWVelocity;
|
||||
double _lastNSVelocity;
|
||||
|
||||
/**
|
||||
* the instrument manager creates a default instance of us,
|
||||
* if no explicit GPS is specific in the aircraft's instruments.xml file.
|
||||
* This allows default route-following to work with the generic autopilot.
|
||||
* This flat is set in that case, to inform us we're a 'fake' installation,
|
||||
* and not to worry about electrical power or similar.
|
||||
*/
|
||||
bool _defaultGPSMode;
|
||||
|
||||
std::string _mode;
|
||||
GPSListener* _listener;
|
||||
Config _config;
|
||||
FGRouteMgr* _routeMgr;
|
||||
|
||||
bool _ref_navaid_set;
|
||||
double _ref_navaid_elapsed;
|
||||
FGPositionedRef _ref_navaid;
|
||||
|
||||
std::string _name;
|
||||
int _num;
|
||||
|
||||
|
@ -356,17 +319,7 @@ private:
|
|||
SGGeod _scratchPos;
|
||||
SGPropertyNode_ptr _scratchNode;
|
||||
bool _scratchValid;
|
||||
|
||||
// search data
|
||||
int _searchResultIndex;
|
||||
std::string _searchQuery;
|
||||
FGPositioned::Type _searchType;
|
||||
bool _searchExact;
|
||||
FGPositionedList _searchResults;
|
||||
bool _searchIsRoute; ///< set if 'search' is actually the current route
|
||||
bool _searchHasNext; ///< is there a result after this one?
|
||||
bool _searchNames; ///< set if we're searching names instead of idents
|
||||
|
||||
|
||||
// turn data
|
||||
bool _computeTurnData; ///< do we need to update the turn data?
|
||||
bool _anticipateTurn; ///< are we anticipating the next turn or not?
|
||||
|
@ -380,18 +333,19 @@ private:
|
|||
|
||||
std::auto_ptr<flightgear::WayptController> _wayptController;
|
||||
|
||||
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
|
||||
flightgear::WayptRef _prevWaypt;
|
||||
flightgear::WayptRef _currentWaypt;
|
||||
|
||||
// autopilot drive properties
|
||||
SGPropertyNode_ptr _apDrivingFlag;
|
||||
SGPropertyNode_ptr _apTrueHeading;
|
||||
SGPropertyNode_ptr _apTargetAltitudeFt;
|
||||
SGPropertyNode_ptr _apAltitudeLock;
|
||||
|
||||
|
||||
simgear::TiedPropertyList _tiedProperties;
|
||||
|
||||
SGSharedPtr<flightgear::FlightPlan> _route;
|
||||
|
||||
SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
|
||||
SGPropertyChangeCallback<GPS> _callbackRouteActivated;
|
||||
};
|
||||
|
||||
#endif // __INSTRUMENTS_GPS_HXX
|
||||
|
|
|
@ -94,7 +94,7 @@ void FGInstrumentMgr::init()
|
|||
nd->setStringValue("name", "gps");
|
||||
nd->setIntValue("number", 0);
|
||||
_instruments.push_back("gps[0]");
|
||||
set_subsystem("gps[0]", new GPS(nd));
|
||||
set_subsystem("gps[0]", new GPS(nd, true /* default GPS mode */));
|
||||
}
|
||||
|
||||
// bind() created instruments before init.
|
||||
|
|
|
@ -265,6 +265,12 @@ int FlightPlan::clearWayptsWithFlag(WayptFlag flag)
|
|||
}
|
||||
}
|
||||
|
||||
// test if the current leg will be removed
|
||||
bool currentIsBeingCleared = false;
|
||||
if (_currentIndex >= 0) {
|
||||
currentIsBeingCleared = _legs[_currentIndex]->waypoint()->flag(flag);
|
||||
}
|
||||
|
||||
_currentIndex -= count;
|
||||
|
||||
// now delete and remove
|
||||
|
@ -276,11 +282,18 @@ int FlightPlan::clearWayptsWithFlag(WayptFlag flag)
|
|||
|
||||
lockDelegate();
|
||||
_waypointsChanged = true;
|
||||
if (count > 0) {
|
||||
if ((count > 0) || currentIsBeingCleared) {
|
||||
_currentWaypointChanged = true;
|
||||
}
|
||||
|
||||
_legs.erase(it, _legs.end());
|
||||
|
||||
if (_legs.empty()) { // maybe all legs were deleted
|
||||
if (_delegate) {
|
||||
_delegate->runCleared();
|
||||
}
|
||||
}
|
||||
|
||||
unlockDelegate();
|
||||
return rf.numDeleted();
|
||||
}
|
||||
|
@ -300,6 +313,23 @@ void FlightPlan::setCurrentIndex(int index)
|
|||
_currentWaypointChanged = true;
|
||||
unlockDelegate();
|
||||
}
|
||||
|
||||
void FlightPlan::finish()
|
||||
{
|
||||
if (_currentIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
lockDelegate();
|
||||
_currentIndex = -1;
|
||||
_currentWaypointChanged = true;
|
||||
|
||||
if (_delegate) {
|
||||
_delegate->runFinished();
|
||||
}
|
||||
|
||||
unlockDelegate();
|
||||
}
|
||||
|
||||
int FlightPlan::findWayptIndex(const SGGeod& aPos) const
|
||||
{
|
||||
|
@ -1214,5 +1244,11 @@ void FlightPlan::Delegate::runCleared()
|
|||
if (_inner) _inner->runCleared();
|
||||
cleared();
|
||||
}
|
||||
|
||||
|
||||
void FlightPlan::Delegate::runFinished()
|
||||
{
|
||||
if (_inner) _inner->runFinished();
|
||||
endOfFlightPlan();
|
||||
}
|
||||
|
||||
} // of namespace flightgear
|
||||
|
|
|
@ -104,7 +104,7 @@ public:
|
|||
virtual void waypointsChanged() { }
|
||||
virtual void cleared() { }
|
||||
virtual void currentWaypointChanged() { }
|
||||
|
||||
virtual void endOfFlightPlan() { }
|
||||
protected:
|
||||
Delegate();
|
||||
|
||||
|
@ -116,6 +116,7 @@ public:
|
|||
void runWaypointsChanged();
|
||||
void runCurrentWaypointChanged();
|
||||
void runCleared();
|
||||
void runFinished();
|
||||
|
||||
friend class FlightPlan;
|
||||
|
||||
|
@ -135,6 +136,8 @@ public:
|
|||
|
||||
void setCurrentIndex(int index);
|
||||
|
||||
void finish();
|
||||
|
||||
Leg* currentLeg() const;
|
||||
Leg* nextLeg() const;
|
||||
Leg* previousLeg() const;
|
||||
|
|
|
@ -1690,10 +1690,12 @@ PositionedID NavDataCache::createPOI(FGPositioned::Type ty, const std::string& i
|
|||
true /* spatial index */);
|
||||
}
|
||||
|
||||
void NavDataCache::removePOI(FGPositioned::Type ty, const std::string& aIdent)
|
||||
bool NavDataCache::removePOI(FGPositioned::Type ty, const std::string& aIdent)
|
||||
{
|
||||
d->removePositionedWithIdent(ty, aIdent);
|
||||
// should remove from the live cache too?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NavDataCache::setAirportMetar(const string& icao, bool hasMetar)
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
|
||||
PositionedID createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos);
|
||||
|
||||
void removePOI(FGPositioned::Type ty, const std::string& aIdent);
|
||||
bool removePOI(FGPositioned::Type ty, const std::string& aIdent);
|
||||
|
||||
void dropGroundnetFor(PositionedID aAirport);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <queue>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
|
@ -85,10 +86,10 @@ FGPositioned::createUserWaypoint(const std::string& aIdent, const SGGeod& aPos)
|
|||
return cache->loadById(id);
|
||||
}
|
||||
|
||||
void FGPositioned::deleteUserWaypoint(const std::string& aIdent)
|
||||
bool FGPositioned::deleteUserWaypoint(const std::string& aIdent)
|
||||
{
|
||||
NavDataCache* cache = NavDataCache::instance();
|
||||
cache->removePOI(WAYPOINT, aIdent);
|
||||
return cache->removePOI(WAYPOINT, aIdent);
|
||||
}
|
||||
|
||||
|
||||
|
@ -335,8 +336,8 @@ FGPositionedRef FGPositioned::loadByIdImpl(PositionedID id)
|
|||
}
|
||||
|
||||
FGPositioned::TypeFilter::TypeFilter(Type aTy) :
|
||||
mMinType(aTy),
|
||||
mMaxType(aTy)
|
||||
mMinType(LAST_TYPE),
|
||||
mMaxType(INVALID)
|
||||
{
|
||||
addType(aTy);
|
||||
}
|
||||
|
@ -352,6 +353,23 @@ void FGPositioned::TypeFilter::addType(Type aTy)
|
|||
mMaxType = std::max(mMaxType, aTy);
|
||||
}
|
||||
|
||||
FGPositioned::TypeFilter
|
||||
FGPositioned::TypeFilter::fromString(const std::string& aFilterSpec)
|
||||
{
|
||||
if (aFilterSpec.empty()) {
|
||||
throw sg_format_exception("empty filter spec:", aFilterSpec);
|
||||
}
|
||||
|
||||
string_list parts = simgear::strutils::split(aFilterSpec, ",");
|
||||
TypeFilter f;
|
||||
|
||||
BOOST_FOREACH(std::string token, parts) {
|
||||
f.addType(typeFromName(token));
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool
|
||||
FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
|
||||
{
|
||||
|
|
|
@ -163,7 +163,7 @@ public:
|
|||
class TypeFilter : public Filter
|
||||
{
|
||||
public:
|
||||
TypeFilter(Type aTy);
|
||||
TypeFilter(Type aTy = INVALID);
|
||||
virtual bool pass(FGPositioned* aPos) const;
|
||||
|
||||
virtual Type minType() const
|
||||
|
@ -173,7 +173,10 @@ public:
|
|||
{ return mMaxType; }
|
||||
|
||||
void addType(Type aTy);
|
||||
|
||||
static TypeFilter fromString(const std::string& aFilterSpec);
|
||||
private:
|
||||
|
||||
std::vector<Type> types;
|
||||
Type mMinType, mMaxType;
|
||||
};
|
||||
|
@ -266,7 +269,7 @@ public:
|
|||
static const char* nameForType(Type aTy);
|
||||
|
||||
static FGPositioned* createUserWaypoint(const std::string& aIdent, const SGGeod& aPos);
|
||||
static void deleteUserWaypoint(const std::string& aIdent);
|
||||
static bool deleteUserWaypoint(const std::string& aIdent);
|
||||
protected:
|
||||
friend class flightgear::NavDataCache;
|
||||
|
||||
|
|
|
@ -415,11 +415,11 @@ static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRe
|
|||
|
||||
static const char* waypointCommonGetMember(naContext c, Waypt* wpt, const char* fieldName, naRef* out)
|
||||
{
|
||||
if (!strcmp(fieldName, "wp_name")) *out = stringToNasal(c, wpt->ident());
|
||||
if (!strcmp(fieldName, "wp_name") || !strcmp(fieldName, "id")) *out = stringToNasal(c, wpt->ident());
|
||||
else if (!strcmp(fieldName, "wp_type")) *out = stringToNasal(c, wpt->type());
|
||||
else if (!strcmp(fieldName, "wp_role")) *out = wayptFlagToNasal(c, wpt->flags());
|
||||
else if (!strcmp(fieldName, "wp_lat")) *out = naNum(wpt->position().getLatitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_lon")) *out = naNum(wpt->position().getLongitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_lat") || !strcmp(fieldName, "lat")) *out = naNum(wpt->position().getLatitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_lon") || !strcmp(fieldName, "lon")) *out = naNum(wpt->position().getLongitudeDeg());
|
||||
else if (!strcmp(fieldName, "wp_parent_name")) {
|
||||
Procedure* proc = dynamic_cast<Procedure*>(wpt->owner());
|
||||
*out = proc ? stringToNasal(c, proc->ident()) : naNil();
|
||||
|
@ -497,6 +497,7 @@ static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* o
|
|||
if (!strcmp(fieldName, "parents")) {
|
||||
*out = naNewVector(c);
|
||||
naVec_append(*out, fpLegPrototype);
|
||||
naVec_append(*out, waypointPrototype);
|
||||
} else if (!strcmp(fieldName, "index")) {
|
||||
*out = naNum(leg->index());
|
||||
} else if (!strcmp(fieldName, "alt_cstr")) {
|
||||
|
@ -589,6 +590,11 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
|
|||
return;
|
||||
}
|
||||
|
||||
if (naIsNil(value)) {
|
||||
fp->setDeparture(static_cast<FGAirport*>(NULL));
|
||||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
} else if (!strcmp(fieldName, "destination")) {
|
||||
FGAirport* apt = airportGhost(value);
|
||||
|
@ -611,7 +617,7 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
|
|||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
naRuntimeError(c, "bad argument type setting departure runway");
|
||||
} else if (!strcmp(fieldName, "destination_runway")) {
|
||||
FGRunway* rwy = runwayGhost(value);
|
||||
if (rwy){
|
||||
|
@ -619,7 +625,7 @@ static void flightplanGhostSetMember(naContext c, void* g, naRef field, naRef va
|
|||
return;
|
||||
}
|
||||
|
||||
naRuntimeError(c, "bad argument type setting departure");
|
||||
naRuntimeError(c, "bad argument type setting destination runway");
|
||||
} else if (!strcmp(fieldName, "sid")) {
|
||||
Procedure* proc = procedureGhost(value);
|
||||
if (proc && (proc->type() == PROCEDURE_SID)) {
|
||||
|
@ -1388,6 +1394,21 @@ static naRef f_airport_getApproach(naContext c, naRef me, int argc, naRef* args)
|
|||
return ghostForProcedure(c, apt->findApproachWithIdent(ident));
|
||||
}
|
||||
|
||||
static naRef f_airport_findBestRunway(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
if (!apt) {
|
||||
naRuntimeError(c, "findBestRunway called on non-airport object");
|
||||
}
|
||||
|
||||
SGGeod pos;
|
||||
if (!geodFromArgs(args, 0, argc, pos)) {
|
||||
naRuntimeError(c, "findBestRunway must be passed a position");
|
||||
}
|
||||
|
||||
return ghostForRunway(c, apt->findBestRunwayForPos(pos));
|
||||
}
|
||||
|
||||
static naRef f_airport_toString(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FGAirport* apt = airportGhost(me);
|
||||
|
@ -1754,13 +1775,17 @@ public:
|
|||
{
|
||||
callDelegateMethod("cleared");
|
||||
}
|
||||
|
||||
virtual void endOfFlightPlan()
|
||||
{
|
||||
callDelegateMethod("endOfFlightPlan");
|
||||
}
|
||||
private:
|
||||
|
||||
void callDelegateMethod(const char* method)
|
||||
{
|
||||
naRef f;
|
||||
naMember_cget(_nasal->context(), _instance, method, &f);
|
||||
if (naIsNil(f)) {
|
||||
if (naMember_cget(_nasal->context(), _instance, method, &f) == 0) {
|
||||
return; // no method on the delegate
|
||||
}
|
||||
|
||||
|
@ -2131,6 +2156,16 @@ static naRef f_flightplan_pathGeod(naContext c, naRef me, int argc, naRef* args)
|
|||
return result;
|
||||
}
|
||||
|
||||
static naRef f_flightplan_finish(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
FlightPlan* fp = flightplanGhost(me);
|
||||
if (!fp) {
|
||||
naRuntimeError(c, "flightplan.finish called on non-flightplan object");
|
||||
}
|
||||
|
||||
fp->finish();
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_leg_setSpeed(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
|
@ -2376,6 +2411,7 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
|
|||
hashset(c, airportPrototype, "getSid", naNewFunc(c, naNewCCode(c, f_airport_getSid)));
|
||||
hashset(c, airportPrototype, "getStar", naNewFunc(c, naNewCCode(c, f_airport_getStar)));
|
||||
hashset(c, airportPrototype, "getIAP", naNewFunc(c, naNewCCode(c, f_airport_getApproach)));
|
||||
hashset(c, airportPrototype, "findBestRunwayForPos", naNewFunc(c, naNewCCode(c, f_airport_findBestRunway)));
|
||||
hashset(c, airportPrototype, "tostring", naNewFunc(c, naNewCCode(c, f_airport_toString)));
|
||||
|
||||
flightplanPrototype = naNewHash(c);
|
||||
|
@ -2394,6 +2430,7 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave)
|
|||
hashset(c, flightplanPrototype, "clearWPType", naNewFunc(c, naNewCCode(c, f_flightplan_clearWPType)));
|
||||
hashset(c, flightplanPrototype, "clone", naNewFunc(c, naNewCCode(c, f_flightplan_clone)));
|
||||
hashset(c, flightplanPrototype, "pathGeod", naNewFunc(c, naNewCCode(c, f_flightplan_pathGeod)));
|
||||
hashset(c, flightplanPrototype, "finish", naNewFunc(c, naNewCCode(c, f_flightplan_finish)));
|
||||
|
||||
waypointPrototype = naNewHash(c);
|
||||
hashset(c, gcSave, "wayptProto", waypointPrototype);
|
||||
|
|
|
@ -406,8 +406,8 @@ static naRef f_findWithinRange(nasal::CallContext ctx)
|
|||
static naRef f_findByIdent(nasal::CallContext ctx)
|
||||
{
|
||||
std::string prefix = ctx.requireArg<std::string>(0);
|
||||
|
||||
FGPositioned::TypeFilter filter(FGPositioned::typeFromName(ctx.getArg<std::string>(1)));
|
||||
std::string typeSpec = ctx.getArg<std::string>(1);
|
||||
FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec));
|
||||
bool exact = ctx.getArg<bool>(2, false);
|
||||
|
||||
return ctx.to_nasal( FGPositioned::findAllWithIdent(prefix, &filter, exact) );
|
||||
|
@ -416,8 +416,8 @@ static naRef f_findByIdent(nasal::CallContext ctx)
|
|||
static naRef f_findByName(nasal::CallContext ctx)
|
||||
{
|
||||
std::string prefix = ctx.requireArg<std::string>(0);
|
||||
|
||||
FGPositioned::TypeFilter filter(FGPositioned::typeFromName(ctx.getArg<std::string>(1)));
|
||||
std::string typeSpec = ctx.getArg<std::string>(1);
|
||||
FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec));
|
||||
|
||||
return ctx.to_nasal( FGPositioned::findAllWithName(prefix, &filter, false) );
|
||||
}
|
||||
|
@ -501,7 +501,7 @@ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c, naRef gcSave)
|
|||
.method("getStar", &FGAirport::findSTARWithIdent)
|
||||
.method("getIAP", &FGAirport::findApproachWithIdent)
|
||||
.method("tostring", &FGAirport::toString);
|
||||
|
||||
|
||||
nasal::Hash globals(globalsRef, c),
|
||||
positioned( globals.createHash("positioned") );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue