]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scripting/NasalPositioned.cxx
More route-manager functionality moved to Nasal.
[flightgear.git] / src / Scripting / NasalPositioned.cxx
index 031e85f1f64c101752c57052d1370a5d319076e2..53a3a41e7eca335acf7d5daa6508c702bfaef641 100644 (file)
 #include <Airports/simple.hxx>
 #include <Airports/dynamics.hxx>
 #include <Airports/parking.hxx>
+#include <Scripting/NasalSys.hxx>
 #include <Navaids/navlist.hxx>
 #include <Navaids/procedure.hxx>
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Scenery/scenery.hxx>
 #include <ATC/CommStation.hxx>
-#include <Navaids/route.hxx>
+#include <Navaids/FlightPlan.hxx>
 #include <Navaids/waypoint.hxx>
 #include <Navaids/fix.hxx>
 #include <Autopilot/route_mgr.hxx>
@@ -74,10 +75,12 @@ static const char* fixGhostGetMember(naContext c, void* g, naRef field, naRef* o
 naGhostType FixGhostType = { positionedGhostDestroy, "fix", fixGhostGetMember, 0 };
 
 static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out);
+static void waypointGhostSetMember(naContext c, void* g, naRef field, naRef value);
+
 naGhostType WayptGhostType = { wayptGhostDestroy, 
   "waypoint",
   wayptGhostGetMember,
-  0};
+  waypointGhostSetMember};
 
 static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* out);
 static void legGhostSetMember(naContext c, void* g, naRef field, naRef value);
@@ -381,6 +384,20 @@ static const char* waypointCommonGetMember(naContext c, Waypt* wpt, const char*
   return "";
 }
 
+static void waypointCommonSetMember(naContext c, Waypt* wpt, const char* fieldName, naRef value)
+{
+  if (!strcmp(fieldName, "wp_role")) {
+    if (!naIsString(value)) naRuntimeError(c, "wp_role must be a string");
+    if (wpt->owner() != NULL) naRuntimeError(c, "cannot override wp_role on waypoint with parent");
+    WayptFlag f = wayptFlagFromString(naStr_data(value));
+    if (f == 0) {
+      naRuntimeError(c, "unrecognized wp_role value %s", naStr_data(value));
+    }
+    
+    wpt->setFlag(f, true);
+  }
+}
+
 static const char* wayptGhostGetMember(naContext c, void* g, naRef field, naRef* out)
 {
   const char* fieldName = naStr_data(field);
@@ -449,21 +466,19 @@ static const char* legGhostGetMember(naContext c, void* g, naRef field, naRef* o
   return ""; // success
 }
 
+static void waypointGhostSetMember(naContext c, void* g, naRef field, naRef value)
+{
+  const char* fieldName = naStr_data(field);
+  Waypt* wpt = (Waypt*) g;
+  waypointCommonSetMember(c, wpt, fieldName, value);
+}
+
 static void legGhostSetMember(naContext c, void* g, naRef field, naRef value)
 {
   const char* fieldName = naStr_data(field);
   FlightPlan::Leg* leg = (FlightPlan::Leg*) g;
-  
-  if (!strcmp(fieldName, "wp_role")) {
-    if (!naIsString(value)) naRuntimeError(c, "wp_role must be a string");
-    if (leg->waypoint()->owner() != NULL) naRuntimeError(c, "cannot override wp_role on waypoint with parent");
-    WayptFlag f = wayptFlagFromString(naStr_data(value));
-    if (f == 0) {
-      naRuntimeError(c, "unrecognized wp_role value %s", naStr_data(value));
-    }
     
-    leg->waypoint()->setFlag(f, true);
-  }
+  waypointCommonSetMember(c, leg->waypoint(), fieldName, value);
 }
 
 static const char* flightplanGhostGetMember(naContext c, void* g, naRef field, naRef* out)
@@ -1307,6 +1322,16 @@ static naRef f_airport_getApproach(naContext c, naRef me, int argc, naRef* args)
   return ghostForProcedure(c, apt->findApproachWithIdent(ident));
 }
 
+static naRef f_airport_toString(naContext c, naRef me, int argc, naRef* args)
+{
+  FGAirport* apt = airportGhost(me);
+  if (!apt) {
+    naRuntimeError(c, "airport.tostring called on non-airport object");
+  }
+  
+  return stringToNasal(c, "an airport " + apt->ident());
+}
+
 // Returns vector of data hash for navaid of a <type>, nil on error
 // navaids sorted by ascending distance 
 // navinfo([<lat>,<lon>],[<type>],[<id>])
@@ -1616,6 +1641,108 @@ static naRef f_route(naContext c, naRef me, int argc, naRef* args)
   return naNil();
 }
 
+class NasalFPDelegate : public FlightPlan::Delegate
+{
+public:
+  NasalFPDelegate(FlightPlan* fp, FGNasalSys* sys, naRef ins) :
+    _nasal(sys),
+    _plan(fp),
+    _instance(ins)
+  {
+    SG_LOG(SG_NASAL, SG_INFO, "created Nasal delegate for " << fp);
+    _gcSaveKey = _nasal->gcSave(ins);
+  }
+  
+  virtual ~NasalFPDelegate()
+  {
+    SG_LOG(SG_NASAL, SG_INFO, "destroying Nasal delegate for " << _plan);
+    _nasal->gcRelease(_gcSaveKey);
+  }
+  
+  virtual void departureChanged()
+  {
+    callDelegateMethod("departureChanged");
+  }
+  
+  virtual void arrivalChanged()
+  {
+    callDelegateMethod("arrivalChanged");
+  }
+  
+  virtual void waypointsChanged()
+  {
+    callDelegateMethod("waypointsChanged");
+  }
+  
+  virtual void currentWaypointChanged()
+  {
+    callDelegateMethod("currentWaypointChanged");
+  }
+private:
+  
+  void callDelegateMethod(const char* method)
+  {
+    naRef f;
+    naMember_cget(_nasal->context(), _instance, method, &f);
+    if (naIsNil(f)) {
+      return; // no method on the delegate
+    }
+    
+    naRef arg[1];
+    arg[0] = ghostForFlightPlan(_nasal->context(), _plan);
+    _nasal->callMethod(f, _instance, 1, arg, naNil());
+  }
+  
+  FGNasalSys* _nasal;
+  FlightPlan* _plan;
+  naRef _instance;
+  int _gcSaveKey;
+};
+
+class NasalFPDelegateFactory : public FlightPlan::DelegateFactory
+{
+public:
+  NasalFPDelegateFactory(naRef code)
+  {
+    _nasal = (FGNasalSys*) globals->get_subsystem("nasal");
+    _func = code;
+    _gcSaveKey = _nasal->gcSave(_func);
+  }
+  
+  ~NasalFPDelegateFactory()
+  {
+    _nasal->gcRelease(_gcSaveKey);
+  }
+  
+  virtual FlightPlan::Delegate* createFlightPlanDelegate(FlightPlan* fp)
+  {
+    naRef args[1];
+    args[0] = ghostForFlightPlan(_nasal->context(), fp);
+    naRef instance = _nasal->call(_func, 1, args, naNil());
+    if (naIsNil(instance)) {
+      return NULL;
+    }
+    
+    return new NasalFPDelegate(fp, _nasal, instance);
+  }
+private:
+  FGNasalSys* _nasal;
+  naRef _func;
+  int _gcSaveKey;
+};
+
+static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args)
+{
+  if ((argc < 1) || !naIsFunc(args[0])) {
+    naRuntimeError(c, "non-function argument to registerFlightPlanDelegate");
+  }
+  
+  NasalFPDelegateFactory* factory = new NasalFPDelegateFactory(args[0]);
+  FlightPlan::registerDelegateFactory(factory);
+  
+  return naNil();
+}
+
 static WayptRef wayptFromArg(naRef arg)
 {
   WayptRef r = wayptGhost(arg);
@@ -2076,6 +2203,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
   { "findNavaidsByID", f_findNavaidsByIdent },
   { "findFixesByID", f_findFixesByIdent },
   { "flightplan", f_route },
+  { "registerFlightPlanDelegate", f_registerFPDelegate },
   { "createWP", f_createWP },
   { "createWPFrom", f_createWPFrom },
   { "airwaysRoute", f_airwaySearch },
@@ -2103,6 +2231,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, "tostring", naNewFunc(c, naNewCCode(c, f_airport_toString)));
   
     flightplanPrototype = naNewHash(c);
     hashset(c, gcSave, "flightplanProto", flightplanPrototype);