From 78afdb3c2227e75fc1542b3992dcea26181d98cf Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 28 Apr 2012 23:28:12 +0100 Subject: [PATCH] Convert all the Nasal wrappers around FGPositioned to use ghost-member-access Lazy-ness is good. Along the way, expose the course on ILS/LOC navaids to Nasal. --- src/Scripting/NasalPositioned.cxx | 277 +++++++++++++++++++----------- src/Scripting/NasalPositioned.hxx | 7 - 2 files changed, 174 insertions(+), 110 deletions(-) diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index dcf2c8197..9127e149c 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -51,6 +52,15 @@ static void positionedGhostDestroy(void* g); static void wayptGhostDestroy(void* g); naGhostType PositionedGhostType = { positionedGhostDestroy, "positioned" }; +static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRef* out); +naGhostType AirportGhostType = { positionedGhostDestroy, "airport", airportGhostGetMember, 0 }; + +static const char* navaidGhostGetMember(naContext c, void* g, naRef field, naRef* out); +naGhostType NavaidGhostType = { positionedGhostDestroy, "navaid", navaidGhostGetMember, 0 }; + +static const char* runwayGhostGetMember(naContext c, void* g, naRef field, naRef* out); +naGhostType RunwayGhostType = { positionedGhostDestroy, "runway", runwayGhostGetMember, 0 }; + static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out); naGhostType WayptGhostType = { wayptGhostDestroy, @@ -79,6 +89,27 @@ static FGPositioned* positionedGhost(naRef r) return 0; } +static FGAirport* airportGhost(naRef r) +{ + if (naGhost_type(r) == &AirportGhostType) + return (FGAirport*) naGhost_ptr(r); + return 0; +} + +static FGNavRecord* navaidGhost(naRef r) +{ + if (naGhost_type(r) == &NavaidGhostType) + return (FGNavRecord*) naGhost_ptr(r); + return 0; +} + +static FGRunway* runwayGhost(naRef r) +{ + if (naGhost_type(r) == &RunwayGhostType) + return (FGRunway*) naGhost_ptr(r); + return 0; +} + static void positionedGhostDestroy(void* g) { FGPositioned* pos = (FGPositioned*)g; @@ -115,6 +146,36 @@ naRef ghostForPositioned(naContext c, const FGPositioned* pos) return naNewGhost(c, &PositionedGhostType, (void*) pos); } +naRef ghostForAirport(naContext c, const FGAirport* apt) +{ + if (!apt) { + return naNil(); + } + + FGPositioned::get(apt); // take a ref + return naNewGhost2(c, &AirportGhostType, (void*) apt); +} + +naRef ghostForNavaid(naContext c, const FGNavRecord* n) +{ + if (!n) { + return naNil(); + } + + FGPositioned::get(n); // take a ref + return naNewGhost2(c, &NavaidGhostType, (void*) n); +} + +naRef ghostForRunway(naContext c, const FGRunway* r) +{ + if (!r) { + return naNil(); + } + + FGPositioned::get(r); // take a ref + return naNewGhost2(c, &RunwayGhostType, (void*) r); +} + naRef ghostForWaypt(naContext c, const flightgear::Waypt* wpt) { if (!wpt) { @@ -125,34 +186,36 @@ naRef ghostForWaypt(naContext c, const flightgear::Waypt* wpt) return naNewGhost2(c, &WayptGhostType, (void*) wpt); } -naRef hashForAirport(naContext c, const FGAirport* apt) +static const char* airportGhostGetMember(naContext c, void* g, naRef field, naRef* out) { - std::string id = apt->ident(); - std::string name = apt->name(); - - // build runways hash - naRef rwys = naNewHash(c); + const char* fieldName = naStr_data(field); + FGAirport* apt = (FGAirport*) g; + + if (!strcmp(fieldName, "parents")) { + *out = naNewVector(c); + naVec_append(*out, airportPrototype); + } else if (!strcmp(fieldName, "id")) *out = stringToNasal(c, apt->ident()); + else if (!strcmp(fieldName, "name")) *out = stringToNasal(c, apt->name()); + else if (!strcmp(fieldName, "lat")) *out = naNum(apt->getLatitude()); + else if (!strcmp(fieldName, "lon")) *out = naNum(apt->getLongitude()); + else if (!strcmp(fieldName, "elevation")) { + *out = naNum(apt->getElevation() * SG_FEET_TO_METER); + } else if (!strcmp(fieldName, "has_metar")) { + *out = naNum(apt->getMetar()); + } else if (!strcmp(fieldName, "runways")) { + *out = naNewHash(c); for(unsigned int r=0; rnumRunways(); ++r) { FGRunway* rwy(apt->getRunwayByIndex(r)); naRef rwyid = stringToNasal(c, rwy->ident()); - naRef rwydata = hashForRunway(c, rwy); - naHash_set(rwys, rwyid, rwydata); + naRef rwydata = ghostForRunway(c, rwy); + naHash_set(*out, rwyid, rwydata); } + + } else { + return 0; + } - naRef aptdata = naNewHash(c); - hashset(c, aptdata, "id", stringToNasal(c, id)); - hashset(c, aptdata, "name", stringToNasal(c, name)); - hashset(c, aptdata, "lat", naNum(apt->getLatitude())); - hashset(c, aptdata, "lon", naNum(apt->getLongitude())); - hashset(c, aptdata, "elevation", naNum(apt->getElevation() * SG_FEET_TO_METER)); - hashset(c, aptdata, "has_metar", naNum(apt->getMetar())); - hashset(c, aptdata, "runways", rwys); - hashset(c, aptdata, "_positioned", ghostForPositioned(c, apt)); - naRef parents = naNewVector(c); - naVec_append(parents, airportPrototype); - hashset(c, aptdata, "parents", parents); - - return aptdata; + return ""; } static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out) @@ -192,51 +255,58 @@ static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* return ""; // success } -naRef hashForRunway(naContext c, FGRunway* rwy) +static const char* runwayGhostGetMember(naContext c, void* g, naRef field, naRef* out) { - naRef rwyid = stringToNasal(c, rwy->ident()); - naRef rwydata = naNewHash(c); -#define HASHSET(s,l,n) naHash_set(rwydata, naStr_fromdata(naNewString(c),s,l),n) - HASHSET("id", 2, rwyid); - HASHSET("lat", 3, naNum(rwy->latitude())); - HASHSET("lon", 3, naNum(rwy->longitude())); - HASHSET("heading", 7, naNum(rwy->headingDeg())); - HASHSET("length", 6, naNum(rwy->lengthM())); - HASHSET("width", 5, naNum(rwy->widthM())); - HASHSET("threshold", 9, naNum(rwy->displacedThresholdM())); - HASHSET("stopway", 7, naNum(rwy->stopwayM())); - - if (rwy->ILS()) { - HASHSET("ils_frequency_mhz", 17, naNum(rwy->ILS()->get_freq() / 100.0)); - HASHSET("ils", 3, hashForNavRecord(c, rwy->ILS(), SGGeod())); - } - - HASHSET("_positioned", 11, ghostForPositioned(c, rwy)); -#undef HASHSET - return rwydata; + const char* fieldName = naStr_data(field); + FGRunway* rwy = (FGRunway*) g; + + if (!strcmp(fieldName, "id")) *out = stringToNasal(c, rwy->ident()); + else if (!strcmp(fieldName, "lat")) *out = naNum(rwy->latitude()); + else if (!strcmp(fieldName, "lon")) *out = naNum(rwy->longitude()); + else if (!strcmp(fieldName, "heading")) *out = naNum(rwy->headingDeg()); + else if (!strcmp(fieldName, "length")) *out = naNum(rwy->lengthM()); + else if (!strcmp(fieldName, "width")) *out = naNum(rwy->widthM()); + else if (!strcmp(fieldName, "threshold")) *out = naNum(rwy->displacedThresholdM()); + else if (!strcmp(fieldName, "stopway")) *out = naNum(rwy->stopwayM()); + else if (!strcmp(fieldName, "ils_frequency_mhz")) { + *out = rwy->ILS() ? naNum(rwy->ILS()->get_freq() / 100.0) : naNil(); + } else if (!strcmp(fieldName, "ils")) { + *out = ghostForNavaid(c, rwy->ILS()); + } else { + return 0; + } + + return ""; } -naRef hashForNavRecord(naContext c, const FGNavRecord* nav, const SGGeod& rel) +static const char* navaidGhostGetMember(naContext c, void* g, naRef field, naRef* out) { - naRef navdata = naNewHash(c); -#define HASHSET(s,l,n) naHash_set(navdata, naStr_fromdata(naNewString(c),s,l),n) - HASHSET("id", 2, stringToNasal(c, nav->ident())); - HASHSET("name", 4, stringToNasal(c, nav->name())); - HASHSET("frequency", 9, naNum(nav->get_freq())); - HASHSET("lat", 3, naNum(nav->get_lat())); - HASHSET("lon", 3, naNum(nav->get_lon())); - HASHSET("elevation", 9, naNum(nav->get_elev_ft() * SG_FEET_TO_METER)); - HASHSET("type", 4, stringToNasal(c, nav->nameForType(nav->type()))); - -// FIXME - get rid of these, people should use courseAndDistance instead - HASHSET("distance", 8, naNum(SGGeodesy::distanceNm( rel, nav->geod() ) * SG_NM_TO_METER ) ); - HASHSET("bearing", 7, naNum(SGGeodesy::courseDeg( rel, nav->geod() ) ) ); - - // record the real object as a ghost for further operations - HASHSET("_positioned",11, ghostForPositioned(c, nav)); -#undef HASHSET - - return navdata; + const char* fieldName = naStr_data(field); + FGNavRecord* nav = (FGNavRecord*) g; + + if (!strcmp(fieldName, "id")) *out = stringToNasal(c, nav->ident()); + else if (!strcmp(fieldName, "name")) *out = stringToNasal(c, nav->name()); + else if (!strcmp(fieldName, "lat")) *out = naNum(nav->get_lat()); + else if (!strcmp(fieldName, "lon")) *out = naNum(nav->get_lon()); + else if (!strcmp(fieldName, "elevation")) { + *out = naNum(nav->get_elev_ft() * SG_FEET_TO_METER); + } else if (!strcmp(fieldName, "type")) { + *out = stringToNasal(c, nav->nameForType(nav->type())); + } else if (!strcmp(fieldName, "frequency")) { + *out = naNum(nav->get_freq()); + } else if (!strcmp(fieldName, "course")) { + if ((nav->type() == FGPositioned::ILS) || (nav->type() == FGPositioned::LOC)) { + double radial = nav->get_multiuse(); + SG_NORMALIZE_RANGE(radial, 0.0, 360.0); + *out = naNum(radial); + } else { + *out = naNil(); + } + } else { + return 0; + } + + return ""; } static bool hashIsCoord(naRef h) @@ -264,13 +334,6 @@ bool geodFromHash(naRef ref, SGGeod& result) return true; } - naRef ghost = naHash_cget(ref, (char*) "_waypt"); - if (!naIsNil(ghost)) { - flightgear::Waypt* w = wayptGhost(ghost); - result = w->position(); - return true; - } - // then check for manual latitude / longitude names naRef lat = naHash_cget(ref, (char*) "lat"); naRef lon = naHash_cget(ref, (char*) "lon"); @@ -300,6 +363,29 @@ static int geodFromArgs(naRef* args, int offset, int argc, SGGeod& result) return 0; } + if (naIsGhost(args[offset])) { + naGhostType* gt = naGhost_type(args[offset]); + if (gt == &AirportGhostType) { + result = airportGhost(args[offset])->geod(); + return 1; + } + + if (gt == &NavaidGhostType) { + result = navaidGhost(args[offset])->geod(); + return 1; + } + + if (gt == &RunwayGhostType) { + result = runwayGhost(args[offset])->geod(); + return 1; + } + + if (gt == &WayptGhostType) { + result = wayptGhost(args[offset])->position(); + return 1; + } + } + if (geodFromHash(args[offset], result)) { return 1; } @@ -462,7 +548,7 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args) if(!apt) return naNil(); } - return hashForAirport(c, apt); + return ghostForAirport(c, apt); } static naRef f_findAirportsWithinRange(naContext c, naRef me, int argc, naRef* args) @@ -488,7 +574,7 @@ static naRef f_findAirportsWithinRange(naContext c, naRef me, int argc, naRef* a BOOST_FOREACH(FGPositionedRef a, apts) { FGAirport* apt = (FGAirport*) a.get(); - naVec_append(r, hashForAirport(c, apt)); + naVec_append(r, ghostForAirport(c, apt)); } return r; @@ -513,30 +599,15 @@ static naRef f_findAirportsByICAO(naContext c, naRef me, int argc, naRef* args) BOOST_FOREACH(FGPositionedRef a, apts) { FGAirport* apt = (FGAirport*) a.get(); - naVec_append(r, hashForAirport(c, apt)); + naVec_append(r, ghostForAirport(c, apt)); } return r; } -static FGAirport* airportFromMe(naRef me) -{ - naRef ghost = naHash_cget(me, (char*) "_positioned"); - if (naIsNil(ghost)) { - return NULL; - } - - FGPositioned* pos = positionedGhost(ghost); - if (pos && FGAirport::isAirportType(pos)) { - return (FGAirport*) pos; - } - - return NULL; -} - static naRef f_airport_tower(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.tower called on non-airport object"); } @@ -552,7 +623,7 @@ static naRef f_airport_tower(naContext c, naRef me, int argc, naRef* args) static naRef f_airport_comms(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.comms called on non-airport object"); } @@ -581,7 +652,7 @@ static naRef f_airport_comms(naContext c, naRef me, int argc, naRef* args) static naRef f_airport_runway(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.runway called on non-airport object"); } @@ -595,12 +666,12 @@ static naRef f_airport_runway(naContext c, naRef me, int argc, naRef* args) return naNil(); } - return hashForRunway(c, apt->getRunwayByIdent(ident)); + return ghostForRunway(c, apt->getRunwayByIdent(ident)); } static naRef f_airport_sids(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.sids called on non-airport object"); } @@ -630,7 +701,7 @@ static naRef f_airport_sids(naContext c, naRef me, int argc, naRef* args) static naRef f_airport_stars(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.stars called on non-airport object"); } @@ -660,7 +731,7 @@ static naRef f_airport_stars(naContext c, naRef me, int argc, naRef* args) static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args) { - FGAirport* apt = airportFromMe(me); + FGAirport* apt = airportGhost(me); if (!apt) { naRuntimeError(c, "airport.parking called on non-airport object"); } @@ -757,7 +828,7 @@ static naRef f_navinfo(naContext c, naRef me, int argc, naRef* args) naRef reply = naNewVector(c); for( nav_list_type::const_iterator it = navlist.begin(); it != navlist.end(); ++it ) { - naVec_append( reply, hashForNavRecord(c, *it, pos) ); + naVec_append( reply, ghostForNavaid(c, *it) ); } return reply; } @@ -785,7 +856,7 @@ static naRef f_findNavaidsWithinRange(naContext c, naRef me, int argc, naRef* ar BOOST_FOREACH(FGPositionedRef a, navs) { FGNavRecord* nav = (FGNavRecord*) a.get(); - naVec_append(r, hashForNavRecord(c, nav, pos)); + naVec_append(r, ghostForNavaid(c, nav)); } return r; @@ -812,7 +883,7 @@ static naRef f_findNavaidByFrequency(naContext c, naRef me, int argc, naRef* arg return naNil(); } - return hashForNavRecord(c, navs.front().ptr(), pos); + return ghostForNavaid(c, navs.front().ptr()); } static naRef f_findNavaidsByFrequency(naContext c, naRef me, int argc, naRef* args) @@ -835,7 +906,7 @@ static naRef f_findNavaidsByFrequency(naContext c, naRef me, int argc, naRef* ar nav_list_type navs = globals->get_navlist()->findAllByFreq(freqMhz, pos, type); BOOST_FOREACH(nav_rec_ptr a, navs) { - naVec_append(r, hashForNavRecord(c, a.ptr(), pos)); + naVec_append(r, ghostForNavaid(c, a.ptr())); } return r; @@ -861,7 +932,7 @@ static naRef f_findNavaidsByIdent(naContext c, naRef me, int argc, naRef* args) nav_list_type navs = globals->get_navlist()->findByIdentAndFreq(pos, ident, 0.0, type); BOOST_FOREACH(nav_rec_ptr a, navs) { - naVec_append(r, hashForNavRecord(c, a.ptr(), pos)); + naVec_append(r, ghostForNavaid(c, a.ptr())); } return r; @@ -1036,7 +1107,7 @@ static naRef f_waypoint_navaid(naContext c, naRef me, int argc, naRef* args) case FGPositioned::DME: case FGPositioned::TACAN: { FGNavRecord* nav = (FGNavRecord*) pos; - return hashForNavRecord(c, nav, globals->get_aircraft_position()); + return ghostForNavaid(c, nav); } default: @@ -1056,7 +1127,7 @@ static naRef f_waypoint_airport(naContext c, naRef me, int argc, naRef* args) return naNil(); } - return hashForAirport(c, (FGAirport*) pos); + return ghostForAirport(c, (FGAirport*) pos); } static naRef f_waypoint_runway(naContext c, naRef me, int argc, naRef* args) @@ -1071,7 +1142,7 @@ static naRef f_waypoint_runway(naContext c, naRef me, int argc, naRef* args) return naNil(); } - return hashForRunway(c, (FGRunway*) pos); + return ghostForRunway(c, (FGRunway*) pos); } // Table of extension functions. Terminate with zeros. diff --git a/src/Scripting/NasalPositioned.hxx b/src/Scripting/NasalPositioned.hxx index 5fbec2650..a3b7514d2 100644 --- a/src/Scripting/NasalPositioned.hxx +++ b/src/Scripting/NasalPositioned.hxx @@ -25,13 +25,6 @@ // forward decls class SGGeod; -class FGAirport; -class FGRunway; -class FGNavRecord; - -naRef hashForAirport(naContext c, const FGAirport* apt); -naRef hashForRunway(naContext c, FGRunway* rwy); -naRef hashForNavRecord(naContext c, const FGNavRecord* nav, const SGGeod& rel); bool geodFromHash(naRef ref, SGGeod& result); -- 2.39.5