1
0
Fork 0

Split huge NasalSys header apart.

This commit is contained in:
James Turner 2013-02-09 15:33:05 +00:00
parent 6baaee696f
commit 7b663cd7f7
12 changed files with 348 additions and 200 deletions

View file

@ -43,6 +43,7 @@
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx>
#include <Scripting/NasalModelData.hxx>
#include <Sound/fg_fx.hxx>
#include "AIBase.hxx"

View file

@ -25,6 +25,8 @@
#include "FGFontCache.hxx"
#include "FGColor.hxx"
using std::string;
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING };
static const int FORMAT_BUFSIZE = 255;
static const int RESIZE_MARGIN = 7;
@ -204,7 +206,7 @@ struct GUIInfo
FGPUIDialog *dialog;
SGPropertyNode_ptr node;
vector <SGBinding *> bindings;
std::vector <SGBinding *> bindings;
int key;
string label, legend, text, format;
format_type fmt_type;
@ -1153,7 +1155,7 @@ FGPUIDialog::setupObject (puObject *object, SGPropertyNode *props)
}
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
std::vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
if (bindings.size() > 0) {
info->key = props->getIntValue("keynum", -1);
if (props->hasValue("key"))
@ -1485,7 +1487,7 @@ fgValueList::make_list()
vname = _props->getStringValue("property-name");
}
vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
std::vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
_list = new char *[value_nodes.size() + 1];
unsigned int i;
for (i = 0; i < value_nodes.size(); i++) {

View file

@ -36,6 +36,7 @@ using simgear::PropertyList;
using std::cout;
using std::endl;
using std::map;
using std::string;
FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
value(0.0)

View file

@ -133,11 +133,11 @@ void FGJoystickInput::init()
if (configMap.hasConfiguration(name)) {
named = configMap.configurationForDeviceName(name);
string source = named->getStringValue("source", "user defined");
std::string source = named->getStringValue("source", "user defined");
SG_LOG(SG_INPUT, SG_INFO, "... found joystick: " << source);
} else if ((named = configMap.configurationForDeviceName("default"))) {
string source = named->getStringValue("source", "user defined");
std::string source = named->getStringValue("source", "user defined");
SG_LOG(SG_INPUT, SG_INFO, "No config found for joystick \"" << name
<< "\"\nUsing default: \"" << source << '"');
@ -205,7 +205,7 @@ void FGJoystickInput::postinit()
//
std::ostringstream str;
str << "__js" << i;
string module = str.str();
std::string module = str.str();
nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
PropertyList nasal = js_node->getChildren("nasal");

View file

@ -101,7 +101,7 @@ void FGKeyboardInput::init()
void FGKeyboardInput::postinit()
{
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
string module = "__kbd";
std::string module = "__kbd";
SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
if (key_nodes == NULL) {
SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");

View file

@ -43,6 +43,7 @@
#include <Viewer/renderer.hxx>
#include <Viewer/splash.hxx>
#include <Scripting/NasalSys.hxx>
#include <Scripting/NasalModelData.hxx>
#include "scenery.hxx"
#include "SceneryPager.hxx"

View file

@ -8,15 +8,18 @@ set(SOURCES
NasalClipboard.cxx
NasalCondition.cxx
NasalString.cxx
NasalModelData.cxx
)
set(HEADERS
NasalSys.hxx
NasalSys_private.hxx
NasalPositioned.hxx
NasalCanvas.hxx
NasalClipboard.hxx
NasalCondition.hxx
NasalString.hxx
NasalModelData.hxx
)
if(WIN32)

View file

@ -0,0 +1,94 @@
#include "NasalModelData.hxx"
#include <simgear/debug/logstream.hxx>
#include "NasalSys.hxx"
#include <Main/globals.hxx>
// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to
// such a class, then it lets modelLoaded() run the <load> script, and the
// 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::load()
{
std::stringstream m;
m << "__model" << _module_id++;
_module = m.str();
SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_str());
const char *s = _load ? _load->getStringValue() : "";
FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
naRef arg[2];
arg[0] = nasalSys->propNodeGhost(_root);
arg[1] = nasalSys->propNodeGhost(_prop);
nasalSys->createModule(_module.c_str(), _path.c_str(), s, strlen(s),
_root, 2, arg);
}
void FGNasalModelData::unload()
{
if (_module.empty())
return;
FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
if(!nasalSys) {
SG_LOG(SG_NASAL, SG_WARN, "Trying to run an <unload> script "
"without Nasal subsystem present.");
return;
}
SG_LOG(SG_NASAL, SG_DEBUG, "Unloading nasal module " << _module.c_str());
if (_unload)
{
const char *s = _unload->getStringValue();
nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s), _root);
}
nasalSys->deleteModule(_module.c_str());
}
void FGNasalModelDataProxy::modelLoaded(const std::string& path, SGPropertyNode *prop,
osg::Node *)
{
FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
if(!nasalSys) {
SG_LOG(SG_NASAL, SG_WARN, "Trying to run a <load> script "
"without Nasal subsystem present.");
return;
}
if(!prop)
return;
SGPropertyNode *nasal = prop->getNode("nasal");
if(!nasal)
return;
SGPropertyNode* load = nasal->getNode("load");
SGPropertyNode* unload = nasal->getNode("unload");
if ((!load) && (!unload))
return;
_data = new FGNasalModelData(_root, path, prop, load, unload);
// register Nasal module to be created and loaded in the main thread.
nasalSys->registerToLoad(_data);
}
FGNasalModelDataProxy::~FGNasalModelDataProxy()
{
FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
// when necessary, register Nasal module to be destroyed/unloaded
// in the main thread.
if ((_data.valid())&&(nasalSys))
nasalSys->registerToUnload(_data);
}

View file

@ -0,0 +1,74 @@
// Copyright (C) 2013 James Turner
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef NASAL_MODEL_DATA_HXX
#define NASAL_MODEL_DATA_HXX
#include <simgear/nasal/nasal.h>
#include <simgear/scene/model/modellib.hxx>
using std::string;
/** 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<FGNasalModelData> _data;
};
#endif // of NASAL_MODEL_DATA_HXX

View file

@ -30,6 +30,8 @@
#include <simgear/debug/BufferedLogCallback.hxx>
#include "NasalSys.hxx"
#include "NasalSys_private.hxx"
#include "NasalModelData.hxx"
#include "NasalPositioned.hxx"
#include "NasalCanvas.hxx"
#include "NasalClipboard.hxx"
@ -178,6 +180,7 @@ bool FGNasalSys::parseAndRun(const char* sourceCode)
return true;
}
#if 0
FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
{
FGNasalScript* script = new FGNasalScript();
@ -199,6 +202,7 @@ FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
script->_gcKey = gcSave(script->_code);
return script;
}
#endif
// The get/setprop functions accept a *list* of strings and walk
// through the property tree with them to find the appropriate node.
@ -339,7 +343,11 @@ static naRef f_logprint(naContext c, naRef me, int argc, naRef* args)
if(naIsNil(s)) continue;
buf += naStr_data(s);
}
SG_LOG(SG_NASAL, (sgDebugPriority)(int) priority.num, buf);
// use the nasal source file and line for the message location, since
// that's more useful than the location here!
sglog().log(SG_NASAL, (sgDebugPriority)(int) priority.num,
naStr_data(naGetSourceFile(c, 0)),
naGetLine(c, 0), buf);
return naNum(buf.length());
}
@ -475,6 +483,60 @@ static naRef f_resolveDataPath(naContext c, naRef me, int argc, naRef* args)
return naStr_fromdata(naNewString(c), const_cast<char*>(pdata), strlen(pdata));
}
class NasalCommand : public SGCommandMgr::Command
{
public:
NasalCommand(FGNasalSys* sys, naRef f) :
_sys(sys),
_func(f)
{
_gcRoot = sys->gcSave(f);
}
virtual ~NasalCommand()
{
_sys->gcRelease(_gcRoot);
}
virtual bool operator()(const SGPropertyNode* aNode)
{
_sys->setCmdArg(const_cast<SGPropertyNode*>(aNode));
naRef args[1];
args[0] = _sys->cmdArgGhost();
_sys->callMethod(_func, naNil(), 1, args, naNil() /* locals */);
return true;
}
private:
FGNasalSys* _sys;
naRef _func;
int _gcRoot;
};
static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args)
{
if(argc != 2 || !naIsString(args[0]) || !naIsFunc(args[1]))
naRuntimeError(c, "bad arguments to addcommand()");
naRef func = args[1];
NasalCommand* cmd = new NasalCommand(nasalSys, func);
globals->get_commands()->addCommandObject(naStr_data(args[0]), cmd);
return naNil();
}
static naRef f_removeCommand(naContext c, naRef me, int argc, naRef* args)
{
SGCommandMgr::Command* cmd = globals->get_commands()->getCommand(naStr_data(args[0]));
// SGCommandMgr::Command* cmd = globals->get_commands()->removeCommand(naStr_data(args[0]))
delete cmd;
return naNil();
}
// Parse XML file.
// parsexml(<path> [, <start-tag> [, <end-tag> [, <data> [, <pi>]]]]);
//
@ -539,6 +601,8 @@ static struct { const char* name; naCFunction func; } funcs[] = {
{ "settimer", f_settimer },
{ "_setlistener", f_setlistener },
{ "removelistener", f_removelistener },
{ "addcommand", f_addCommand },
{ "removecommand", f_removeCommand },
{ "_cmdarg", f_cmdarg },
{ "_interpolate", f_interpolate },
{ "rand", f_rand },
@ -556,6 +620,11 @@ naRef FGNasalSys::cmdArgGhost()
return propNodeGhost(_cmdArg);
}
void FGNasalSys::setCmdArg(SGPropertyNode* aNode)
{
_cmdArg = aNode;
}
void FGNasalSys::init()
{
int i;
@ -1034,6 +1103,15 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
return naNum(_listener.size());
}
void FGNasalSys::registerToLoad(FGNasalModelData *data)
{
_loadList.push(data);
}
void FGNasalSys::registerToUnload(FGNasalModelData *data)
{
_unloadList.push(data);
}
// FGNasalListener class.
@ -1132,90 +1210,6 @@ bool FGNasalListener::changed(SGPropertyNode* node)
}
}
// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to
// such a class, then it lets modelLoaded() run the <load> script, and the
// 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::load()
{
std::stringstream m;
m << "__model" << _module_id++;
_module = m.str();
SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_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(), _path.c_str(), s, strlen(s),
_root, 2, arg);
}
void FGNasalModelData::unload()
{
if (_module.empty())
return;
if(!nasalSys) {
SG_LOG(SG_NASAL, SG_WARN, "Trying to run an <unload> script "
"without Nasal subsystem present.");
return;
}
SG_LOG(SG_NASAL, SG_DEBUG, "Unloading nasal module " << _module.c_str());
if (_unload)
{
const char *s = _unload->getStringValue();
nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s), _root);
}
nasalSys->deleteModule(_module.c_str());
}
void FGNasalModelDataProxy::modelLoaded(const string& path, SGPropertyNode *prop,
osg::Node *)
{
if(!nasalSys) {
SG_LOG(SG_NASAL, SG_WARN, "Trying to run a <load> script "
"without Nasal subsystem present.");
return;
}
if(!prop)
return;
SGPropertyNode *nasal = prop->getNode("nasal");
if(!nasal)
return;
SGPropertyNode* load = nasal->getNode("load");
SGPropertyNode* unload = nasal->getNode("unload");
if ((!load) && (!unload))
return;
_data = new FGNasalModelData(_root, path, prop, load, unload);
// register Nasal module to be created and loaded in the main thread.
nasalSys->registerToLoad(_data);
}
FGNasalModelDataProxy::~FGNasalModelDataProxy()
{
// when necessary, register Nasal module to be destroyed/unloaded
// in the main thread.
if ((_data.valid())&&(nasalSys))
nasalSys->registerToUnload(_data);
}
// NasalXMLVisitor class: handles EasyXML visitor callback for parsexml()
//
NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) :

View file

@ -5,9 +5,8 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/nasal/nasal.h>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/xml/easyxml.hxx>
#include <simgear/threads/SGQueue.hxx>
#include <simgear/props/props.hxx>
#include <map>
@ -15,58 +14,10 @@
class FGNasalScript;
class FGNasalListener;
class SGCondition;
class FGNasalModelData;
namespace simgear { class BufferedLogCallback; }
/** 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<FGNasalModelData> _data;
};
SGPropertyNode* ghostToPropNode(naRef ref);
SGCondition* conditionGhost(naRef r);
@ -94,7 +45,7 @@ public:
// this function. The "name" argument specifies the "file name"
// for the source code that will be printed in Nasal stack traces
// on error.
FGNasalScript* parseScript(const char* src, const char* name=0);
// FGNasalScript* parseScript(const char* src, const char* name=0);
// Implementation of the settimer extension function
void setTimer(naContext c, int argc, naRef* args);
@ -106,6 +57,8 @@ public:
// Returns a ghost wrapper for the current _cmdArg
naRef cmdArgGhost();
void setCmdArg(SGPropertyNode* aNode);
// Callbacks for command and timer bindings
virtual bool handleCommand( const char* moduleName,
const char* fileName,
@ -135,8 +88,8 @@ public:
naRef propNodeGhost(SGPropertyNode* handle);
void registerToLoad(FGNasalModelData* data) { _loadList.push(data);}
void registerToUnload(FGNasalModelData* data) { _unloadList.push(data);}
void registerToLoad(FGNasalModelData* data);
void registerToUnload(FGNasalModelData* data);
// can't call this 'globals' due to naming clash
naRef nasalGlobals() const
@ -159,7 +112,7 @@ public:
simgear::BufferedLogCallback* log() const
{ return _log; }
private:
friend class FGNasalScript;
//friend class FGNasalScript;
friend class FGNasalListener;
friend class FGNasalModuleListener;
@ -181,13 +134,14 @@ private:
// Listener
std::map<int, FGNasalListener *> _listener;
vector<FGNasalListener *> _dead_listener;
std::vector<FGNasalListener *> _dead_listener;
static int _listenerId;
void loadPropertyScripts();
void loadPropertyScripts(SGPropertyNode* n);
void loadScriptDirectory(simgear::Dir nasalDir);
void addModule(string moduleName, simgear::PathList scripts);
void addModule(std::string moduleName, simgear::PathList scripts);
void logError(naContext);
naRef parse(const char* filename, const char* buf, int len);
naRef genPropsModule();
@ -207,7 +161,7 @@ public:
void handleTimer(NasalTimer* t);
};
#if 0
class FGNasalScript {
public:
~FGNasalScript() { _nas->gcRelease(_gcKey); }
@ -218,60 +172,13 @@ public:
return naGetError(_nas->_context) == 0;
}
FGNasalSys* sys() const { return _nas; }
private:
friend class FGNasalSys;
naRef _code;
int _gcKey;
FGNasalSys* _nas;
};
class FGNasalListener : public SGPropertyChangeListener {
public:
FGNasalListener(SGPropertyNode* node, naRef code, FGNasalSys* nasal,
int key, int id, int init, int type);
virtual ~FGNasalListener();
virtual void valueChanged(SGPropertyNode* node);
virtual void childAdded(SGPropertyNode* parent, SGPropertyNode* child);
virtual void childRemoved(SGPropertyNode* parent, SGPropertyNode* child);
private:
bool changed(SGPropertyNode* node);
void call(SGPropertyNode* which, naRef mode);
friend class FGNasalSys;
SGPropertyNode_ptr _node;
naRef _code;
int _gcKey;
int _id;
FGNasalSys* _nas;
int _init;
int _type;
unsigned int _active;
bool _dead;
long _last_int;
double _last_float;
string _last_string;
};
class NasalXMLVisitor : public XMLVisitor {
public:
NasalXMLVisitor(naContext c, int argc, naRef* args);
virtual ~NasalXMLVisitor() { naFreeContext(_c); }
virtual void startElement(const char* tag, const XMLAttributes& a);
virtual void endElement(const char* tag);
virtual void data(const char* str, int len);
virtual void pi(const char* target, const char* data);
private:
void call(naRef func, int num, naRef a = naNil(), naRef b = naNil());
naRef make_string(const char* s, int n = -1);
naContext _c;
naRef _start_element, _end_element, _data, _pi;
};
#endif
#endif // __NASALSYS_HXX

View file

@ -0,0 +1,71 @@
// Copyright (C) 2013 James Turner//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __NASALSYS_PRIVATE_HXX
#define __NASALSYS_PRIVATE_HXX
#include <simgear/props/props.hxx>
#include <simgear/nasal/nasal.h>
#include <simgear/xml/easyxml.hxx>
class FGNasalListener : public SGPropertyChangeListener {
public:
FGNasalListener(SGPropertyNode* node, naRef code, FGNasalSys* nasal,
int key, int id, int init, int type);
virtual ~FGNasalListener();
virtual void valueChanged(SGPropertyNode* node);
virtual void childAdded(SGPropertyNode* parent, SGPropertyNode* child);
virtual void childRemoved(SGPropertyNode* parent, SGPropertyNode* child);
private:
bool changed(SGPropertyNode* node);
void call(SGPropertyNode* which, naRef mode);
friend class FGNasalSys;
SGPropertyNode_ptr _node;
naRef _code;
int _gcKey;
int _id;
FGNasalSys* _nas;
int _init;
int _type;
unsigned int _active;
bool _dead;
long _last_int;
double _last_float;
string _last_string;
};
class NasalXMLVisitor : public XMLVisitor {
public:
NasalXMLVisitor(naContext c, int argc, naRef* args);
virtual ~NasalXMLVisitor() { naFreeContext(_c); }
virtual void startElement(const char* tag, const XMLAttributes& a);
virtual void endElement(const char* tag);
virtual void data(const char* str, int len);
virtual void pi(const char* target, const char* data);
private:
void call(naRef func, int num, naRef a = naNil(), naRef b = naNil());
naRef make_string(const char* s, int n = -1);
naContext _c;
naRef _start_element, _end_element, _data, _pi;
};
#endif // of __NASALSYS_PRIVATE_HXX