A real Timer object in Nasal.
A persistent timer object which can be stopped, started and restarted. Gosh. Has both singleShot and repeating modes.
This commit is contained in:
parent
0f26267647
commit
ab939ff772
1 changed files with 115 additions and 1 deletions
|
@ -28,6 +28,10 @@
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/structure/event_mgr.hxx>
|
#include <simgear/structure/event_mgr.hxx>
|
||||||
#include <simgear/debug/BufferedLogCallback.hxx>
|
#include <simgear/debug/BufferedLogCallback.hxx>
|
||||||
|
|
||||||
|
#include <simgear/nasal/cppbind/from_nasal.hxx>
|
||||||
|
#include <simgear/nasal/cppbind/to_nasal.hxx>
|
||||||
|
#include <simgear/nasal/cppbind/Ghost.hxx>
|
||||||
#include <simgear/nasal/cppbind/NasalHash.hxx>
|
#include <simgear/nasal/cppbind/NasalHash.hxx>
|
||||||
|
|
||||||
#include "NasalSys.hxx"
|
#include "NasalSys.hxx"
|
||||||
|
@ -75,6 +79,91 @@ void FGNasalModuleListener::valueChanged(SGPropertyNode*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
class TimerObj : public SGReferenced
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TimerObj(FGNasalSys* sys, naRef f, naRef self, double interval) :
|
||||||
|
_sys(sys),
|
||||||
|
_func(f),
|
||||||
|
_self(self),
|
||||||
|
_isRunning(false),
|
||||||
|
_interval(interval),
|
||||||
|
_singleShot(false)
|
||||||
|
{
|
||||||
|
char nm[128];
|
||||||
|
snprintf(nm, 128, "nasal-timer-%p", this);
|
||||||
|
_name = nm;
|
||||||
|
_gcRoot = sys->gcSave(f);
|
||||||
|
_gcSelf = sys->gcSave(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TimerObj()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
_sys->gcRelease(_gcRoot);
|
||||||
|
_sys->gcRelease(_gcSelf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
if (_isRunning) {
|
||||||
|
globals->get_event_mgr()->removeTask(_name);
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
if (_isRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRunning = true;
|
||||||
|
if (_singleShot) {
|
||||||
|
globals->get_event_mgr()->addEvent(_name, this, &TimerObj::invoke, _interval);
|
||||||
|
} else {
|
||||||
|
globals->get_event_mgr()->addTask(_name, this, &TimerObj::invoke, _interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop and then start -
|
||||||
|
void restart(double newInterval)
|
||||||
|
{
|
||||||
|
_interval = newInterval;
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void invoke()
|
||||||
|
{
|
||||||
|
naRef *args = NULL;
|
||||||
|
_sys->callMethod(_func, _self, 0, args, naNil() /* locals */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSingleShot(bool aSingleShot)
|
||||||
|
{
|
||||||
|
_singleShot = aSingleShot;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSingleShot() const
|
||||||
|
{ return _singleShot; }
|
||||||
|
private:
|
||||||
|
std::string _name;
|
||||||
|
FGNasalSys* _sys;
|
||||||
|
naRef _func, _self;
|
||||||
|
int _gcRoot, _gcSelf;
|
||||||
|
bool _isRunning;
|
||||||
|
double _interval;
|
||||||
|
bool _singleShot;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SGSharedPtr<TimerObj> TimerObjRef;
|
||||||
|
typedef nasal::Ghost<TimerObjRef> NasalTimerObj;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Read and return file contents in a single buffer. Note use of
|
// Read and return file contents in a single buffer. Note use of
|
||||||
// stat() to get the file size. This is a win32 function, believe it
|
// stat() to get the file size. This is a win32 function, believe it
|
||||||
|
@ -380,6 +469,24 @@ static naRef f_settimer(naContext c, naRef me, int argc, naRef* args)
|
||||||
return naNil();
|
return naNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static naRef f_makeTimer(naContext c, naRef me, int argc, naRef* args)
|
||||||
|
{
|
||||||
|
if (!naIsNum(args[0])) {
|
||||||
|
naRuntimeError(c, "bad interval argument to maketimer");
|
||||||
|
}
|
||||||
|
|
||||||
|
naRef func, self = naNil();
|
||||||
|
if (naIsFunc(args[1])) {
|
||||||
|
func = args[1];
|
||||||
|
} else if ((argc == 3) && naIsFunc(args[2])) {
|
||||||
|
self = args[1];
|
||||||
|
func = args[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerObj* timerObj = new TimerObj(nasalSys, func, self, args[0].num);
|
||||||
|
return NasalTimerObj::create(c, timerObj);
|
||||||
|
}
|
||||||
|
|
||||||
// setlistener(func, property, bool) extension function. Falls through to
|
// setlistener(func, property, bool) extension function. Falls through to
|
||||||
// FGNasalSys::setListener(). See there for docs.
|
// FGNasalSys::setListener(). See there for docs.
|
||||||
static naRef f_setlistener(naContext c, naRef me, int argc, naRef* args)
|
static naRef f_setlistener(naContext c, naRef me, int argc, naRef* args)
|
||||||
|
@ -600,6 +707,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
|
||||||
{ "logprint", f_logprint },
|
{ "logprint", f_logprint },
|
||||||
{ "_fgcommand", f_fgcommand },
|
{ "_fgcommand", f_fgcommand },
|
||||||
{ "settimer", f_settimer },
|
{ "settimer", f_settimer },
|
||||||
|
{ "maketimer", f_makeTimer },
|
||||||
{ "_setlistener", f_setlistener },
|
{ "_setlistener", f_setlistener },
|
||||||
{ "removelistener", f_removelistener },
|
{ "removelistener", f_removelistener },
|
||||||
{ "addcommand", f_addCommand },
|
{ "addcommand", f_addCommand },
|
||||||
|
@ -671,6 +779,12 @@ void FGNasalSys::init()
|
||||||
initNasalCanvas(_globals, _context, _gcHash);
|
initNasalCanvas(_globals, _context, _gcHash);
|
||||||
initNasalCondition(_globals, _context, _gcHash);
|
initNasalCondition(_globals, _context, _gcHash);
|
||||||
|
|
||||||
|
NasalTimerObj::init("Timer")
|
||||||
|
.method("start", &TimerObj::start)
|
||||||
|
.method("stop", &TimerObj::stop)
|
||||||
|
.method("restart", &TimerObj::restart)
|
||||||
|
.member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot);
|
||||||
|
|
||||||
// Now load the various source files in the Nasal directory
|
// Now load the various source files in the Nasal directory
|
||||||
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
|
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
|
||||||
loadScriptDirectory(nasalDir);
|
loadScriptDirectory(nasalDir);
|
||||||
|
@ -1129,7 +1243,7 @@ void FGNasalSys::registerToUnload(FGNasalModelData *data)
|
||||||
_unloadList.push(data);
|
_unloadList.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// FGNasalListener class.
|
// FGNasalListener class.
|
||||||
|
|
||||||
FGNasalListener::FGNasalListener(SGPropertyNode *node, naRef code,
|
FGNasalListener::FGNasalListener(SGPropertyNode *node, naRef code,
|
||||||
|
|
Loading…
Add table
Reference in a new issue