revert meaning of third, optional argument, and add an optional fourth
argument: setlistener(<property>, <func> [, <initial=0> [, <persistent=1>]]) This definition defaults to the old behavior. The fourth argument can be set to zero, in which case the function is only called when the node value has actually changed. It should really default to zero, but then all callers would have to be reviewed, which is a bit too dangerous "shortly" before a release.
This commit is contained in:
parent
b90c95269f
commit
02a813abde
2 changed files with 33 additions and 30 deletions
|
@ -913,13 +913,16 @@ void FGNasalSys::NasalTimer::timerExpired()
|
||||||
|
|
||||||
int FGNasalSys::_listenerId = 0;
|
int FGNasalSys::_listenerId = 0;
|
||||||
|
|
||||||
// setlistener(property, func, bool) extension function. The first argument
|
// setlistener(<property>, <func> [, <initial=0> [, <persistent=1>]])
|
||||||
// is either a ghost (SGPropertyNode_ptr*) or a string (global property
|
// Attaches a callback function to a property (specified as a global
|
||||||
// path), the second is a Nasal function, the optional third one an integer.
|
// property path string or a SGPropertyNode_ptr* ghost). If the third,
|
||||||
// If it is 1, then the listener is executed initially. If it's 2, then
|
// optional argument (default=0) is set to 1, then the function is also
|
||||||
// the listener is only triggered when the node value actually changed. The
|
// called initially. If the fourth, optional argument is set to 0, then the
|
||||||
// setlistener() function returns a unique id number, that can be used
|
// function is only called when the property node value actually changes.
|
||||||
// as argument to the removelistener() function.
|
// Otherwise it's called independent of the value whenever the node is
|
||||||
|
// written to (default). The setlistener() function returns a unique
|
||||||
|
// id number, which is to be used as argument to the removelistener()
|
||||||
|
// function.
|
||||||
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
||||||
{
|
{
|
||||||
SGPropertyNode_ptr node;
|
SGPropertyNode_ptr node;
|
||||||
|
@ -941,10 +944,12 @@ naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
||||||
return naNil();
|
return naNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
int type = argc > 2 && naIsNum(args[2]) ? args[2].num : 0;
|
bool persistent = argc > 3 ? naTrue(args[3]) : true;
|
||||||
FGNasalListener *nl = new FGNasalListener(node, handler, this,
|
FGNasalListener *nl = new FGNasalListener(node, handler, this,
|
||||||
gcSave(handler), _listenerId, type);
|
gcSave(handler), _listenerId, persistent);
|
||||||
node->addChangeListener(nl, type != 0);
|
|
||||||
|
bool initial = argc > 2 && naTrue(args[2]);
|
||||||
|
node->addChangeListener(nl, initial);
|
||||||
|
|
||||||
_listener[_listenerId] = nl;
|
_listener[_listenerId] = nl;
|
||||||
return naNum(_listenerId++);
|
return naNum(_listenerId++);
|
||||||
|
@ -980,20 +985,19 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
|
||||||
|
|
||||||
FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
|
FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
|
||||||
FGNasalSys* nasal, int key, int id,
|
FGNasalSys* nasal, int key, int id,
|
||||||
int type) :
|
bool persistent) :
|
||||||
_node(node),
|
_node(node),
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_gcKey(key),
|
_gcKey(key),
|
||||||
_id(id),
|
_id(id),
|
||||||
_type(type),
|
|
||||||
_nas(nasal),
|
_nas(nasal),
|
||||||
_active(0),
|
_active(0),
|
||||||
_dead(false),
|
_dead(false),
|
||||||
_first_call(true),
|
_first_call(true),
|
||||||
|
_persistent(persistent),
|
||||||
_last_int(0L),
|
_last_int(0L),
|
||||||
_last_float(0.0)
|
_last_float(0.0)
|
||||||
{
|
{
|
||||||
unchanged(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGNasalListener::~FGNasalListener()
|
FGNasalListener::~FGNasalListener()
|
||||||
|
@ -1007,22 +1011,21 @@ void FGNasalListener::valueChanged(SGPropertyNode* node)
|
||||||
// drop recursive listener calls
|
// drop recursive listener calls
|
||||||
if(_active || _dead)
|
if(_active || _dead)
|
||||||
return;
|
return;
|
||||||
if(_type == 2 && !_first_call && unchanged(node))
|
if(_persistent || changed(node) || _first_call) {
|
||||||
return;
|
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
|
||||||
|
_active++;
|
||||||
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
|
_nas->_cmdArg = node;
|
||||||
_active++;
|
_nas->call(_handler, naNil());
|
||||||
_nas->_cmdArg = node;
|
_active--;
|
||||||
_nas->call(_handler, naNil());
|
}
|
||||||
_active--;
|
|
||||||
_first_call = false;
|
_first_call = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGNasalListener::unchanged(SGPropertyNode* node)
|
bool FGNasalListener::changed(SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
SGPropertyNode::Type type = node->getType();
|
SGPropertyNode::Type type = node->getType();
|
||||||
if(type == SGPropertyNode::NONE) return true;
|
if(type == SGPropertyNode::NONE) return false;
|
||||||
if(type == SGPropertyNode::UNSPECIFIED) return false;
|
if(type == SGPropertyNode::UNSPECIFIED) return true;
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
@ -1031,7 +1034,7 @@ bool FGNasalListener::unchanged(SGPropertyNode* node)
|
||||||
case SGPropertyNode::LONG:
|
case SGPropertyNode::LONG:
|
||||||
{
|
{
|
||||||
long l = node->getLongValue();
|
long l = node->getLongValue();
|
||||||
result = l == _last_int;
|
result = l != _last_int;
|
||||||
_last_int = l;
|
_last_int = l;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1039,14 +1042,14 @@ bool FGNasalListener::unchanged(SGPropertyNode* node)
|
||||||
case SGPropertyNode::DOUBLE:
|
case SGPropertyNode::DOUBLE:
|
||||||
{
|
{
|
||||||
double d = node->getDoubleValue();
|
double d = node->getDoubleValue();
|
||||||
result = d == _last_float;
|
result = d != _last_float;
|
||||||
_last_float = d;
|
_last_float = d;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
string s = node->getStringValue();
|
string s = node->getStringValue();
|
||||||
result = s == _last_string;
|
result = s != _last_string;
|
||||||
_last_string = s;
|
_last_string = s;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,11 +132,11 @@ private:
|
||||||
class FGNasalListener : public SGPropertyChangeListener {
|
class FGNasalListener : public SGPropertyChangeListener {
|
||||||
public:
|
public:
|
||||||
FGNasalListener(SGPropertyNode_ptr node, naRef handler,
|
FGNasalListener(SGPropertyNode_ptr node, naRef handler,
|
||||||
FGNasalSys* nasal, int key, int id, int type);
|
FGNasalSys* nasal, int key, int id, bool persistent);
|
||||||
|
|
||||||
~FGNasalListener();
|
~FGNasalListener();
|
||||||
void valueChanged(SGPropertyNode* node);
|
void valueChanged(SGPropertyNode* node);
|
||||||
bool unchanged(SGPropertyNode* node);
|
bool changed(SGPropertyNode* node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class FGNasalSys;
|
friend class FGNasalSys;
|
||||||
|
@ -144,11 +144,11 @@ private:
|
||||||
naRef _handler;
|
naRef _handler;
|
||||||
int _gcKey;
|
int _gcKey;
|
||||||
int _id;
|
int _id;
|
||||||
int _type;
|
|
||||||
FGNasalSys* _nas;
|
FGNasalSys* _nas;
|
||||||
unsigned int _active;
|
unsigned int _active;
|
||||||
bool _dead;
|
bool _dead;
|
||||||
bool _first_call;
|
bool _first_call;
|
||||||
|
bool _persistent;
|
||||||
long _last_int;
|
long _last_int;
|
||||||
double _last_float;
|
double _last_float;
|
||||||
string _last_string;
|
string _last_string;
|
||||||
|
|
Loading…
Add table
Reference in a new issue