+class NasalFPDelegate : public FlightPlan::Delegate
+{
+public:
+ NasalFPDelegate(FlightPlan* fp, FGNasalSys* sys, naRef ins) :
+ _nasal(sys),
+ _plan(fp),
+ _instance(ins)
+ {
+ _gcSaveKey = _nasal->gcSave(ins);
+ }
+
+ virtual ~NasalFPDelegate()
+ {
+ _nasal->gcRelease(_gcSaveKey);
+ }
+
+ virtual void departureChanged()
+ {
+ callDelegateMethod("departureChanged");
+ }
+
+ virtual void arrivalChanged()
+ {
+ callDelegateMethod("arrivalChanged");
+ }
+
+ virtual void waypointsChanged()
+ {
+ callDelegateMethod("waypointsChanged");
+ }
+
+ virtual void currentWaypointChanged()
+ {
+ callDelegateMethod("currentWaypointChanged");
+ }
+
+ virtual void cleared()
+ {
+ callDelegateMethod("cleared");
+ }
+
+ virtual void endOfFlightPlan()
+ {
+ callDelegateMethod("endOfFlightPlan");
+ }
+
+ virtual void activated()
+ {
+ callDelegateMethod("activated");
+ }
+private:
+
+ void callDelegateMethod(const char* method)
+ {
+ naRef f;
+ naContext ctx = naNewContext();
+
+ if (naMember_cget(ctx, _instance, method, &f) != 0) {
+ naRef arg[1];
+ arg[0] = ghostForFlightPlan(ctx, _plan);
+ _nasal->callMethod(f, _instance, 1, arg, naNil());
+ }
+
+ naFreeContext(ctx);
+ }
+
+ 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);
+ }
+
+ virtual ~NasalFPDelegateFactory()
+ {
+ _nasal->gcRelease(_gcSaveKey);
+ }
+
+ virtual FlightPlan::Delegate* createFlightPlanDelegate(FlightPlan* fp)
+ {
+ naRef args[1];
+ naContext ctx = naNewContext();
+ args[0] = ghostForFlightPlan(ctx, fp);
+ naRef instance = _nasal->call(_func, 1, args, naNil());
+
+ FlightPlan::Delegate* result = NULL;
+ if (!naIsNil(instance)) {
+ // will GC-save instance
+ result = new NasalFPDelegate(fp, _nasal, instance);
+ }
+
+ naFreeContext(ctx);
+ return result;
+ }
+private:
+ FGNasalSys* _nasal;
+ naRef _func;
+ int _gcSaveKey;
+};
+
+static std::vector<NasalFPDelegateFactory*> static_nasalDelegateFactories;
+
+void shutdownNasalPositioned()
+{
+ std::vector<NasalFPDelegateFactory*>::iterator it;
+ for (it = static_nasalDelegateFactories.begin();
+ it != static_nasalDelegateFactories.end(); ++it)
+ {
+ FlightPlan::unregisterDelegateFactory(*it);
+ delete (*it);
+ }
+ static_nasalDelegateFactories.clear();
+}
+
+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);
+ static_nasalDelegateFactories.push_back(factory);
+ return naNil();
+}
+