X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalSys.hxx;h=5434844998fb077d1a5df1cab0e771a960703406;hb=1d99401c0427a2a4faae651995736d569f8bbd5e;hp=d1bf0a4c8e8f952cfb0775ff0d0a4f7ad859c509;hpb=fd492a297aee6d40c58f71b1889847b6668af3fd;p=flightgear.git diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index d1bf0a4c8..543484499 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -3,16 +3,70 @@ #include #include +#include #include #include #include +#include #include -SG_USING_STD(map); class FGNasalScript; class FGNasalListener; +class SGCondition; + +/** Nasal model data container. + * load and unload methods must be run in main thread (not thread-safe). */ +class FGNasalModelData : public SGReferenced +{ +public: + /** Constructor to be run in an arbitrary thread. */ + FGNasalModelData(SGPropertyNode *root, const string& path, SGPropertyNode *prop, + SGPropertyNode* load, SGPropertyNode* unload) : + _path(path), + _root(root), _prop(prop), + _load(load), _unload(unload) + { + } + + /** Load hook. Always call from inside the main loop. */ + void load(); + + /** Unload hook. Always call from inside the main loop. */ + void unload(); + +private: + static unsigned int _module_id; + + string _module, _path; + SGPropertyNode_ptr _root, _prop; + SGConstPropertyNode_ptr _load, _unload; +}; + +/** Thread-safe proxy for FGNasalModelData. + * modelLoaded/destroy methods only register the requested + * operation. Actual (un)loading of Nasal module is deferred + * and done in the main loop. */ +class FGNasalModelDataProxy : public simgear::SGModelData +{ +public: + FGNasalModelDataProxy(SGPropertyNode *root = 0) : + _root(root), _data(0) + { + } + + ~FGNasalModelDataProxy(); + + void modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *); + +protected: + SGPropertyNode_ptr _root; + SGSharedPtr _data; +}; + +SGPropertyNode* ghostToPropNode(naRef ref); +SGCondition* conditionGhost(naRef r); class FGNasalSys : public SGSubsystem { @@ -24,7 +78,7 @@ public: // Loads a nasal script from an external file and inserts it as a // global module of the specified name. - void loadModule(SGPath file, const char* moduleName); + bool loadModule(SGPath file, const char* moduleName); // Simple hook to run arbitrary source code. Returns a bool to // indicate successful execution. Does *not* return any Nasal @@ -51,18 +105,59 @@ public: naRef cmdArgGhost(); // Callbacks for command and timer bindings + virtual bool handleCommand( const char* moduleName, + const char* fileName, + const char* src, + const SGPropertyNode* arg = 0 ); virtual bool handleCommand(const SGPropertyNode* arg); - void createModule(const char* moduleName, const char* fileName, - const char* src, int len, const SGPropertyNode* arg=0); + bool createModule(const char* moduleName, const char* fileName, + const char* src, int len, const SGPropertyNode* cmdarg=0, + int argc=0, naRef*args=0); void deleteModule(const char* moduleName); - naRef call(naRef code, int argc, naRef* args, naRef locals); + /** + * Set member of specified hash to given value + */ + void hashset(naRef hash, const char* key, naRef val); + + /** + * Set member of globals hash to given value + */ + void globalsSet(const char* key, naRef val); + naRef call(naRef code, int argc, naRef* args, naRef locals); + + naRef callMethod(naRef code, naRef self, int argc, naRef* args, naRef locals); + + naRef propNodeGhost(SGPropertyNode* handle); + + void registerToLoad(FGNasalModelData* data) { _loadList.push(data);} + void registerToUnload(FGNasalModelData* data) { _unloadList.push(data);} + + // can't call this 'globals' due to naming clash + naRef nasalGlobals() const + { return _globals; } + + naContext context() const + { return _context; } + + // This mechanism is here to allow naRefs to be passed to + // locations "outside" the interpreter. Normally, such a + // reference would be garbage collected unexpectedly. By passing + // it to gcSave and getting a key/handle, it can be cached in a + // globals.__gcsave hash. Be sure to release it with gcRelease + // when done. + int gcSave(naRef r); + void gcRelease(int key); private: friend class FGNasalScript; friend class FGNasalListener; + friend class FGNasalModuleListener; + + SGLockedQueue > _loadList; + SGLockedQueue > _unloadList; // // FGTimer subclass for handling Nasal timer callbacks. @@ -78,25 +173,17 @@ private: }; // Listener - map _listener; + std::map _listener; vector _dead_listener; static int _listenerId; void loadPropertyScripts(); - void hashset(naRef hash, const char* key, naRef val); + void loadPropertyScripts(SGPropertyNode* n); + void loadScriptDirectory(simgear::Dir nasalDir); + void addModule(string moduleName, simgear::PathList scripts); void logError(naContext); naRef parse(const char* filename, const char* buf, int len); naRef genPropsModule(); - naRef propNodeGhost(SGPropertyNode* handle); - - // This mechanism is here to allow naRefs to be passed to - // locations "outside" the interpreter. Normally, such a - // reference would be garbage collected unexpectedly. By passing - // it to gcSave and getting a key/handle, it can be cached in a - // globals.__gcsave hash. Be sure to release it with gcRelease - // when done. - int gcSave(naRef r); - void gcRelease(int key); naContext _context; naRef _globals; @@ -132,7 +219,7 @@ private: class FGNasalListener : public SGPropertyChangeListener { public: FGNasalListener(SGPropertyNode* node, naRef code, FGNasalSys* nasal, - int key, int id, int type); + int key, int id, int init, int type); virtual ~FGNasalListener(); virtual void valueChanged(SGPropertyNode* node); @@ -149,29 +236,16 @@ private: int _gcKey; int _id; FGNasalSys* _nas; + int _init; int _type; unsigned int _active; bool _dead; - bool _first_call; long _last_int; double _last_float; string _last_string; }; -class FGNasalModelData : public simgear::SGModelData { -public: - FGNasalModelData(SGPropertyNode *props = 0) : _props(props), _unload(0) {} - ~FGNasalModelData(); - void modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *); - -private: - string _module; - SGPropertyNode_ptr _props; - SGConstPropertyNode_ptr _unload; -}; - - class NasalXMLVisitor : public XMLVisitor { public: NasalXMLVisitor(naContext c, int argc, naRef* args);