Split huge NasalSys header apart.
This commit is contained in:
parent
6baaee696f
commit
7b663cd7f7
12 changed files with 348 additions and 200 deletions
|
@ -43,6 +43,7 @@
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scripting/NasalSys.hxx>
|
#include <Scripting/NasalSys.hxx>
|
||||||
|
#include <Scripting/NasalModelData.hxx>
|
||||||
#include <Sound/fg_fx.hxx>
|
#include <Sound/fg_fx.hxx>
|
||||||
|
|
||||||
#include "AIBase.hxx"
|
#include "AIBase.hxx"
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "FGFontCache.hxx"
|
#include "FGFontCache.hxx"
|
||||||
#include "FGColor.hxx"
|
#include "FGColor.hxx"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_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 FORMAT_BUFSIZE = 255;
|
||||||
static const int RESIZE_MARGIN = 7;
|
static const int RESIZE_MARGIN = 7;
|
||||||
|
@ -204,7 +206,7 @@ struct GUIInfo
|
||||||
|
|
||||||
FGPUIDialog *dialog;
|
FGPUIDialog *dialog;
|
||||||
SGPropertyNode_ptr node;
|
SGPropertyNode_ptr node;
|
||||||
vector <SGBinding *> bindings;
|
std::vector <SGBinding *> bindings;
|
||||||
int key;
|
int key;
|
||||||
string label, legend, text, format;
|
string label, legend, text, format;
|
||||||
format_type fmt_type;
|
format_type fmt_type;
|
||||||
|
@ -1153,7 +1155,7 @@ FGPUIDialog::setupObject (puObject *object, SGPropertyNode *props)
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
|
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) {
|
if (bindings.size() > 0) {
|
||||||
info->key = props->getIntValue("keynum", -1);
|
info->key = props->getIntValue("keynum", -1);
|
||||||
if (props->hasValue("key"))
|
if (props->hasValue("key"))
|
||||||
|
@ -1485,7 +1487,7 @@ fgValueList::make_list()
|
||||||
vname = _props->getStringValue("property-name");
|
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];
|
_list = new char *[value_nodes.size() + 1];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < value_nodes.size(); i++) {
|
for (i = 0; i < value_nodes.size(); i++) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ using simgear::PropertyList;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
|
FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
|
||||||
value(0.0)
|
value(0.0)
|
||||||
|
|
|
@ -133,11 +133,11 @@ void FGJoystickInput::init()
|
||||||
|
|
||||||
if (configMap.hasConfiguration(name)) {
|
if (configMap.hasConfiguration(name)) {
|
||||||
named = configMap.configurationForDeviceName(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);
|
SG_LOG(SG_INPUT, SG_INFO, "... found joystick: " << source);
|
||||||
|
|
||||||
} else if ((named = configMap.configurationForDeviceName("default"))) {
|
} 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
|
SG_LOG(SG_INPUT, SG_INFO, "No config found for joystick \"" << name
|
||||||
<< "\"\nUsing default: \"" << source << '"');
|
<< "\"\nUsing default: \"" << source << '"');
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ void FGJoystickInput::postinit()
|
||||||
//
|
//
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
str << "__js" << i;
|
str << "__js" << i;
|
||||||
string module = str.str();
|
std::string module = str.str();
|
||||||
nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
|
nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
|
||||||
|
|
||||||
PropertyList nasal = js_node->getChildren("nasal");
|
PropertyList nasal = js_node->getChildren("nasal");
|
||||||
|
|
|
@ -101,7 +101,7 @@ void FGKeyboardInput::init()
|
||||||
void FGKeyboardInput::postinit()
|
void FGKeyboardInput::postinit()
|
||||||
{
|
{
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
|
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
|
||||||
string module = "__kbd";
|
std::string module = "__kbd";
|
||||||
SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
|
SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
|
||||||
if (key_nodes == NULL) {
|
if (key_nodes == NULL) {
|
||||||
SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");
|
SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include <Viewer/renderer.hxx>
|
#include <Viewer/renderer.hxx>
|
||||||
#include <Viewer/splash.hxx>
|
#include <Viewer/splash.hxx>
|
||||||
#include <Scripting/NasalSys.hxx>
|
#include <Scripting/NasalSys.hxx>
|
||||||
|
#include <Scripting/NasalModelData.hxx>
|
||||||
|
|
||||||
#include "scenery.hxx"
|
#include "scenery.hxx"
|
||||||
#include "SceneryPager.hxx"
|
#include "SceneryPager.hxx"
|
||||||
|
|
|
@ -8,15 +8,18 @@ set(SOURCES
|
||||||
NasalClipboard.cxx
|
NasalClipboard.cxx
|
||||||
NasalCondition.cxx
|
NasalCondition.cxx
|
||||||
NasalString.cxx
|
NasalString.cxx
|
||||||
|
NasalModelData.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
NasalSys.hxx
|
NasalSys.hxx
|
||||||
|
NasalSys_private.hxx
|
||||||
NasalPositioned.hxx
|
NasalPositioned.hxx
|
||||||
NasalCanvas.hxx
|
NasalCanvas.hxx
|
||||||
NasalClipboard.hxx
|
NasalClipboard.hxx
|
||||||
NasalCondition.hxx
|
NasalCondition.hxx
|
||||||
NasalString.hxx
|
NasalString.hxx
|
||||||
|
NasalModelData.hxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
94
src/Scripting/NasalModelData.cxx
Normal file
94
src/Scripting/NasalModelData.cxx
Normal 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);
|
||||||
|
}
|
74
src/Scripting/NasalModelData.hxx
Normal file
74
src/Scripting/NasalModelData.hxx
Normal 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
|
|
@ -30,6 +30,8 @@
|
||||||
#include <simgear/debug/BufferedLogCallback.hxx>
|
#include <simgear/debug/BufferedLogCallback.hxx>
|
||||||
|
|
||||||
#include "NasalSys.hxx"
|
#include "NasalSys.hxx"
|
||||||
|
#include "NasalSys_private.hxx"
|
||||||
|
#include "NasalModelData.hxx"
|
||||||
#include "NasalPositioned.hxx"
|
#include "NasalPositioned.hxx"
|
||||||
#include "NasalCanvas.hxx"
|
#include "NasalCanvas.hxx"
|
||||||
#include "NasalClipboard.hxx"
|
#include "NasalClipboard.hxx"
|
||||||
|
@ -178,6 +180,7 @@ bool FGNasalSys::parseAndRun(const char* sourceCode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
|
FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
|
||||||
{
|
{
|
||||||
FGNasalScript* script = new FGNasalScript();
|
FGNasalScript* script = new FGNasalScript();
|
||||||
|
@ -199,6 +202,7 @@ FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
|
||||||
script->_gcKey = gcSave(script->_code);
|
script->_gcKey = gcSave(script->_code);
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// The get/setprop functions accept a *list* of strings and walk
|
// The get/setprop functions accept a *list* of strings and walk
|
||||||
// through the property tree with them to find the appropriate node.
|
// 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;
|
if(naIsNil(s)) continue;
|
||||||
buf += naStr_data(s);
|
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());
|
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));
|
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.
|
// Parse XML file.
|
||||||
// parsexml(<path> [, <start-tag> [, <end-tag> [, <data> [, <pi>]]]]);
|
// parsexml(<path> [, <start-tag> [, <end-tag> [, <data> [, <pi>]]]]);
|
||||||
//
|
//
|
||||||
|
@ -539,6 +601,8 @@ static struct { const char* name; naCFunction func; } funcs[] = {
|
||||||
{ "settimer", f_settimer },
|
{ "settimer", f_settimer },
|
||||||
{ "_setlistener", f_setlistener },
|
{ "_setlistener", f_setlistener },
|
||||||
{ "removelistener", f_removelistener },
|
{ "removelistener", f_removelistener },
|
||||||
|
{ "addcommand", f_addCommand },
|
||||||
|
{ "removecommand", f_removeCommand },
|
||||||
{ "_cmdarg", f_cmdarg },
|
{ "_cmdarg", f_cmdarg },
|
||||||
{ "_interpolate", f_interpolate },
|
{ "_interpolate", f_interpolate },
|
||||||
{ "rand", f_rand },
|
{ "rand", f_rand },
|
||||||
|
@ -556,6 +620,11 @@ naRef FGNasalSys::cmdArgGhost()
|
||||||
return propNodeGhost(_cmdArg);
|
return propNodeGhost(_cmdArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGNasalSys::setCmdArg(SGPropertyNode* aNode)
|
||||||
|
{
|
||||||
|
_cmdArg = aNode;
|
||||||
|
}
|
||||||
|
|
||||||
void FGNasalSys::init()
|
void FGNasalSys::init()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1034,6 +1103,15 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
|
||||||
return naNum(_listener.size());
|
return naNum(_listener.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGNasalSys::registerToLoad(FGNasalModelData *data)
|
||||||
|
{
|
||||||
|
_loadList.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGNasalSys::registerToUnload(FGNasalModelData *data)
|
||||||
|
{
|
||||||
|
_unloadList.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// FGNasalListener class.
|
// 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 class: handles EasyXML visitor callback for parsexml()
|
||||||
//
|
//
|
||||||
NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) :
|
NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) :
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
#include <simgear/nasal/nasal.h>
|
#include <simgear/nasal/nasal.h>
|
||||||
#include <simgear/scene/model/modellib.hxx>
|
|
||||||
#include <simgear/xml/easyxml.hxx>
|
|
||||||
#include <simgear/threads/SGQueue.hxx>
|
#include <simgear/threads/SGQueue.hxx>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -15,58 +14,10 @@
|
||||||
class FGNasalScript;
|
class FGNasalScript;
|
||||||
class FGNasalListener;
|
class FGNasalListener;
|
||||||
class SGCondition;
|
class SGCondition;
|
||||||
|
class FGNasalModelData;
|
||||||
|
|
||||||
namespace simgear { class BufferedLogCallback; }
|
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);
|
SGPropertyNode* ghostToPropNode(naRef ref);
|
||||||
SGCondition* conditionGhost(naRef r);
|
SGCondition* conditionGhost(naRef r);
|
||||||
|
|
||||||
|
@ -94,7 +45,7 @@ public:
|
||||||
// this function. The "name" argument specifies the "file name"
|
// this function. The "name" argument specifies the "file name"
|
||||||
// for the source code that will be printed in Nasal stack traces
|
// for the source code that will be printed in Nasal stack traces
|
||||||
// on error.
|
// 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
|
// Implementation of the settimer extension function
|
||||||
void setTimer(naContext c, int argc, naRef* args);
|
void setTimer(naContext c, int argc, naRef* args);
|
||||||
|
@ -106,6 +57,8 @@ public:
|
||||||
// Returns a ghost wrapper for the current _cmdArg
|
// Returns a ghost wrapper for the current _cmdArg
|
||||||
naRef cmdArgGhost();
|
naRef cmdArgGhost();
|
||||||
|
|
||||||
|
void setCmdArg(SGPropertyNode* aNode);
|
||||||
|
|
||||||
// Callbacks for command and timer bindings
|
// Callbacks for command and timer bindings
|
||||||
virtual bool handleCommand( const char* moduleName,
|
virtual bool handleCommand( const char* moduleName,
|
||||||
const char* fileName,
|
const char* fileName,
|
||||||
|
@ -135,8 +88,8 @@ public:
|
||||||
|
|
||||||
naRef propNodeGhost(SGPropertyNode* handle);
|
naRef propNodeGhost(SGPropertyNode* handle);
|
||||||
|
|
||||||
void registerToLoad(FGNasalModelData* data) { _loadList.push(data);}
|
void registerToLoad(FGNasalModelData* data);
|
||||||
void registerToUnload(FGNasalModelData* data) { _unloadList.push(data);}
|
void registerToUnload(FGNasalModelData* data);
|
||||||
|
|
||||||
// can't call this 'globals' due to naming clash
|
// can't call this 'globals' due to naming clash
|
||||||
naRef nasalGlobals() const
|
naRef nasalGlobals() const
|
||||||
|
@ -159,7 +112,7 @@ public:
|
||||||
simgear::BufferedLogCallback* log() const
|
simgear::BufferedLogCallback* log() const
|
||||||
{ return _log; }
|
{ return _log; }
|
||||||
private:
|
private:
|
||||||
friend class FGNasalScript;
|
//friend class FGNasalScript;
|
||||||
friend class FGNasalListener;
|
friend class FGNasalListener;
|
||||||
friend class FGNasalModuleListener;
|
friend class FGNasalModuleListener;
|
||||||
|
|
||||||
|
@ -181,13 +134,14 @@ private:
|
||||||
|
|
||||||
// Listener
|
// Listener
|
||||||
std::map<int, FGNasalListener *> _listener;
|
std::map<int, FGNasalListener *> _listener;
|
||||||
vector<FGNasalListener *> _dead_listener;
|
std::vector<FGNasalListener *> _dead_listener;
|
||||||
|
|
||||||
static int _listenerId;
|
static int _listenerId;
|
||||||
|
|
||||||
void loadPropertyScripts();
|
void loadPropertyScripts();
|
||||||
void loadPropertyScripts(SGPropertyNode* n);
|
void loadPropertyScripts(SGPropertyNode* n);
|
||||||
void loadScriptDirectory(simgear::Dir nasalDir);
|
void loadScriptDirectory(simgear::Dir nasalDir);
|
||||||
void addModule(string moduleName, simgear::PathList scripts);
|
void addModule(std::string moduleName, simgear::PathList scripts);
|
||||||
void logError(naContext);
|
void logError(naContext);
|
||||||
naRef parse(const char* filename, const char* buf, int len);
|
naRef parse(const char* filename, const char* buf, int len);
|
||||||
naRef genPropsModule();
|
naRef genPropsModule();
|
||||||
|
@ -207,7 +161,7 @@ public:
|
||||||
void handleTimer(NasalTimer* t);
|
void handleTimer(NasalTimer* t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
class FGNasalScript {
|
class FGNasalScript {
|
||||||
public:
|
public:
|
||||||
~FGNasalScript() { _nas->gcRelease(_gcKey); }
|
~FGNasalScript() { _nas->gcRelease(_gcKey); }
|
||||||
|
@ -217,61 +171,14 @@ public:
|
||||||
naCall(_nas->_context, _code, 0, &n, naNil(), naNil());
|
naCall(_nas->_context, _code, 0, &n, naNil(), naNil());
|
||||||
return naGetError(_nas->_context) == 0;
|
return naGetError(_nas->_context) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGNasalSys* sys() const { return _nas; }
|
||||||
private:
|
private:
|
||||||
friend class FGNasalSys;
|
friend class FGNasalSys;
|
||||||
naRef _code;
|
naRef _code;
|
||||||
int _gcKey;
|
int _gcKey;
|
||||||
FGNasalSys* _nas;
|
FGNasalSys* _nas;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
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 // __NASALSYS_HXX
|
#endif // __NASALSYS_HXX
|
||||||
|
|
71
src/Scripting/NasalSys_private.hxx
Normal file
71
src/Scripting/NasalSys_private.hxx
Normal 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
|
Loading…
Reference in a new issue