#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
+#include <sstream>
#include <plib/ul.h>
SGPropertyNode* props = globals->get_props();
naRef val = args[argc-1];
+ bool result = false;
try {
- bool r;
- if(naIsString(val)) r = props->setStringValue(buf, naStr_data(val));
+ if(naIsString(val)) result = props->setStringValue(buf, naStr_data(val));
else {
naRef n = naNumValue(val);
if(naIsNil(n))
naRuntimeError(c, "setprop() value is not string or number");
- r = props->setDoubleValue(buf, n.num);
+ result = props->setDoubleValue(buf, n.num);
}
- if(!r) naRuntimeError(c, "setprop(): property is not writable");
} catch (const string& err) {
naRuntimeError(c, (char *)err.c_str());
}
- return naNil();
+ return naNum(result);
#undef BUFLEN
}
static naRef f_geodinfo(naContext c, naRef me, int argc, naRef* args)
{
#define HASHSET(s,l,n) naHash_set(matdata, naStr_fromdata(naNewString(c),s,l),n)
- if(argc != 2) naRuntimeError(c, "geodinfo() expects 2 arguments: lat, lon");
+ if(argc < 2 || argc > 3)
+ naRuntimeError(c, "geodinfo() expects 2 or 3 arguments: lat, lon [, maxalt]");
double lat = naNumValue(args[0]).num;
double lon = naNumValue(args[1]).num;
- double elev;
+ double elev = argc == 3 ? naNumValue(args[2]).num : 10000;
const SGMaterial *mat;
- if(!globals->get_scenery()->get_elevation_m(lat, lon, 10000.0, elev, &mat))
+ SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
+ if(!globals->get_scenery()->get_elevation_m(geod, elev, &mat))
return naNil();
naRef vec = naNewVector(c);
naVec_append(vec, naNum(elev));
}
-class airport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isAirport(); }
-} airport;
-class seaport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isSeaport(); }
-} seaport;
-class heliport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isHeliport(); }
-} heliport;
+class AirportInfoFilter : public FGAirport::AirportFilter
+{
+public:
+ AirportInfoFilter() : type(FGPositioned::AIRPORT) {
+ }
+
+ virtual FGPositioned::Type minType() const {
+ return type;
+ }
+
+ virtual FGPositioned::Type maxType() const {
+ return type;
+ }
+
+ FGPositioned::Type type;
+};
// Returns data hash for particular or nearest airport of a <type>, or nil
-// on error. Only one side of each runway is contained.
+// on error.
//
// airportinfo(<id>); e.g. "KSFO"
// airportinfo(<type>); type := ("airport"|"seaport"|"heliport")
{
static SGConstPropertyNode_ptr latn = fgGetNode("/position/latitude-deg", true);
static SGConstPropertyNode_ptr lonn = fgGetNode("/position/longitude-deg", true);
- double lat, lon;
+ SGGeod pos;
+ FGAirport* apt = NULL;
- FGAirportList *aptlst = globals->get_airports();
- FGAirport *apt;
if(argc >= 2 && naIsNum(args[0]) && naIsNum(args[1])) {
- lat = args[0].num;
- lon = args[1].num;
+ pos = SGGeod::fromDeg(args[1].num, args[0].num);
args += 2;
argc -= 2;
} else {
- lat = latn->getDoubleValue();
- lon = lonn->getDoubleValue();
+ pos = SGGeod::fromDeg(lonn->getDoubleValue(), latn->getDoubleValue());
}
- double maxRange = 360.0; // expose this? or pick a smaller value?
+ double maxRange = 10000.0; // expose this? or pick a smaller value?
+
+ AirportInfoFilter filter; // defaults to airports only
if(argc == 0) {
- apt = aptlst->search(lon, lat, maxRange, airport);
+ // fall through and use AIRPORT
} else if(argc == 1 && naIsString(args[0])) {
const char *s = naStr_data(args[0]);
- if(!strcmp(s, "airport")) apt = aptlst->search(lon, lat, maxRange, airport);
- else if(!strcmp(s, "seaport")) apt = aptlst->search(lon, lat, maxRange, seaport);
- else if(!strcmp(s, "heliport")) apt = aptlst->search(lon, lat, maxRange, heliport);
- else apt = aptlst->search(s);
+ if(!strcmp(s, "airport")) filter.type = FGPositioned::AIRPORT;
+ else if(!strcmp(s, "seaport")) filter.type = FGPositioned::SEAPORT;
+ else if(!strcmp(s, "heliport")) filter.type = FGPositioned::HELIPORT;
+ else {
+ // user provided an <id>, hopefully
+ apt = FGAirport::findByIdent(s);
+ if (!apt) {
+ naRuntimeError(c, "airportinfo() couldn't find airport: %s", s);
+ return naNil();
+ }
+ }
} else {
naRuntimeError(c, "airportinfo() with invalid function arguments");
return naNil();
}
- if(!apt) return naNil();
- string id = apt->getId();
- string name = apt->getName();
+ if(!apt) {
+ apt = FGAirport::findClosest(pos, maxRange, &filter);
+ if(!apt) return naNil();
+ }
+
+ string id = apt->ident();
+ string name = apt->name();
// set runway hash
naRef rwys = naNewHash(c);
- for (unsigned int r=0; r<apt->numRunways(); ++r) {
+ for(unsigned int r=0; r<apt->numRunways(); ++r) {
FGRunway* rwy(apt->getRunwayByIndex(r));
naRef rwyid = naStr_fromdata(naNewString(c),
HASHSET("heading", 7, naNum(rwy->headingDeg()));
HASHSET("length", 6, naNum(rwy->lengthM()));
HASHSET("width", 5, naNum(rwy->widthM()));
- HASHSET("threshold", 9, naNum(rwy->_displ_thresh * SG_FEET_TO_METER));
- HASHSET("stopway", 7, naNum(rwy->_stopway * SG_FEET_TO_METER));
+ HASHSET("threshold", 9, naNum(rwy->displacedThresholdM()));
+ HASHSET("stopway", 7, naNum(rwy->stopwayM()));
#undef HASHSET
naHash_set(rwys, rwyid, rwydata);
}
const char *s = "nasal-dir-initialized";
SGPropertyNode *signal = fgGetNode("/sim/signals", true);
signal->setBoolValue(s, true);
- signal->removeChildren(s);
+ signal->removeChildren(s, false);
// Pull scripts out of the property tree, too
loadPropertyScripts();
if(n->hasChild("module"))
module = n->getStringValue("module");
- // allow multiple files to be specified within in a single
+ // allow multiple files to be specified within a single
// Nasal module tag
int j = 0;
SGPropertyNode *fn;
j++;
}
- // Old code which only allowed a single file to be specified per module
- /*
- const char* file = n->getStringValue("file");
- if(!n->hasChild("file")) file = 0; // Hrm...
- if(file) {
- SGPath p(globals->get_fg_root());
- p.append(file);
- loadModule(p, module);
- }
- */
-
const char* src = n->getStringValue("script");
if(!n->hasChild("script")) src = 0; // Hrm...
if(src)
return naNil();
}
- int type = argc > 3 && naIsNum(args[3]) ? (int)args[3].num : 1;
+ int init = argc > 2 && naIsNum(args[2]) ? int(args[2].num) : 0;
+ int type = argc > 3 && naIsNum(args[3]) ? int(args[3].num) : 1;
FGNasalListener *nl = new FGNasalListener(node, code, this,
- gcSave(code), _listenerId, type);
+ gcSave(code), _listenerId, init, type);
- bool initial = argc > 2 && naTrue(args[2]);
- node->addChangeListener(nl, initial);
+ node->addChangeListener(nl, init);
_listener[_listenerId] = nl;
return naNum(_listenerId++);
// FGNasalListener class.
FGNasalListener::FGNasalListener(SGPropertyNode *node, naRef code,
- FGNasalSys* nasal, int key, int id, int type) :
+ FGNasalSys* nasal, int key, int id,
+ int init, int type) :
_node(node),
_code(code),
_gcKey(key),
_id(id),
_nas(nasal),
+ _init(init),
_type(type),
_active(0),
_dead(false),
- _first_call(true),
_last_int(0L),
_last_float(0.0)
{
+ if(_type == 0 && !_init)
+ changed(node);
}
FGNasalListener::~FGNasalListener()
void FGNasalListener::valueChanged(SGPropertyNode* node)
{
if(_type < 2 && node != _node) return; // skip child events
- if(_type > 0 || changed(_node) || _first_call)
+ if(_type > 0 || changed(_node) || _init)
call(node, naNum(0));
- _first_call = false;
+ _init = 0;
}
void FGNasalListener::childAdded(SGPropertyNode*, SGPropertyNode* child)
// destructor the <unload> script. The latter happens when the model branch
// is removed from the scene graph.
+unsigned int FGNasalModelData::_module_id = 0;
+
void FGNasalModelData::modelLoaded(const string& path, SGPropertyNode *prop,
osg::Node *)
{
if(!load && !_unload)
return;
- _module = path;
- if(_props)
- _module += ':' + _props->getPath();
+ std::stringstream m;
+ m << "__model" << _module_id++;
+ _module = m.str();
+
const char *s = load ? load->getStringValue() : "";
naRef arg[2];
arg[0] = nasalSys->propNodeGhost(_root);
arg[1] = nasalSys->propNodeGhost(prop);
- nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s),
+ nasalSys->createModule(_module.c_str(), path.c_str(), s, strlen(s),
_root, 2, arg);
_props = 0;
}