add new listener type: setlistner(<prop>, <func> [, <type=0>]);
0 -> trigger whenever property is written to (even if it's the old value; default) 1 -> like 0, but also trigger the function initially 2 -> trigger initially, but then only on changes
This commit is contained in:
parent
44b8f3704a
commit
c979136e5b
2 changed files with 58 additions and 9 deletions
|
@ -896,8 +896,9 @@ int FGNasalSys::_listenerId = 0;
|
||||||
|
|
||||||
// setlistener(property, func, bool) extension function. The first argument
|
// setlistener(property, func, bool) extension function. The first argument
|
||||||
// is either a ghost (SGPropertyNode_ptr*) or a string (global property
|
// is either a ghost (SGPropertyNode_ptr*) or a string (global property
|
||||||
// path), the second is a Nasal function, the optional third one a bool.
|
// path), the second is a Nasal function, the optional third one an integer.
|
||||||
// If the bool is true, then the listener is executed initially. The
|
// If it is 1, then the listener is executed initially. If it's 2, then
|
||||||
|
// the listener is only triggered when the node value actually changed. The
|
||||||
// setlistener() function returns a unique id number, that can be used
|
// setlistener() function returns a unique id number, that can be used
|
||||||
// as argument to the removelistener() function.
|
// as argument to the removelistener() function.
|
||||||
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
||||||
|
@ -921,11 +922,10 @@ naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
|
||||||
return naNil();
|
return naNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initial = argc > 2 && naTrue(args[2]);
|
int type = argc > 2 && naIsNum(args[2]) ? args[2].num : 0;
|
||||||
|
|
||||||
FGNasalListener *nl = new FGNasalListener(node, handler, this,
|
FGNasalListener *nl = new FGNasalListener(node, handler, this,
|
||||||
gcSave(handler), _listenerId);
|
gcSave(handler), _listenerId, type);
|
||||||
node->addChangeListener(nl, initial);
|
node->addChangeListener(nl, type != 0);
|
||||||
|
|
||||||
_listener[_listenerId] = nl;
|
_listener[_listenerId] = nl;
|
||||||
return naNum(_listenerId++);
|
return naNum(_listenerId++);
|
||||||
|
@ -960,15 +960,21 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
|
||||||
// FGNasalListener class.
|
// FGNasalListener class.
|
||||||
|
|
||||||
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) :
|
||||||
_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),
|
||||||
|
_last_int(0L),
|
||||||
|
_last_float(0.0)
|
||||||
{
|
{
|
||||||
|
unchanged(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGNasalListener::~FGNasalListener()
|
FGNasalListener::~FGNasalListener()
|
||||||
|
@ -982,14 +988,51 @@ 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))
|
||||||
|
return;
|
||||||
|
|
||||||
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
|
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
|
||||||
_active++;
|
_active++;
|
||||||
_nas->_cmdArg = node;
|
_nas->_cmdArg = node;
|
||||||
_nas->call(_handler, naNil());
|
_nas->call(_handler, naNil());
|
||||||
_active--;
|
_active--;
|
||||||
|
_first_call = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FGNasalListener::unchanged(SGPropertyNode* node)
|
||||||
|
{
|
||||||
|
SGPropertyNode::Type type = node->getType();
|
||||||
|
if(type == SGPropertyNode::NONE) return true;
|
||||||
|
if(type == SGPropertyNode::UNSPECIFIED) return false;
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
switch(type) {
|
||||||
|
case SGPropertyNode::BOOL:
|
||||||
|
case SGPropertyNode::INT:
|
||||||
|
case SGPropertyNode::LONG:
|
||||||
|
{
|
||||||
|
long l = node->getLongValue();
|
||||||
|
result = l == _last_int;
|
||||||
|
_last_int = l;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::FLOAT:
|
||||||
|
case SGPropertyNode::DOUBLE:
|
||||||
|
{
|
||||||
|
double d = node->getDoubleValue();
|
||||||
|
result = d == _last_float;
|
||||||
|
_last_float = d;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
string s = node->getStringValue();
|
||||||
|
result = s == _last_string;
|
||||||
|
_last_string = s;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -132,10 +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);
|
FGNasalSys* nasal, int key, int id, int type);
|
||||||
|
|
||||||
~FGNasalListener();
|
~FGNasalListener();
|
||||||
void valueChanged(SGPropertyNode* node);
|
void valueChanged(SGPropertyNode* node);
|
||||||
|
bool unchanged(SGPropertyNode* node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class FGNasalSys;
|
friend class FGNasalSys;
|
||||||
|
@ -143,9 +144,14 @@ 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;
|
||||||
|
long _last_int;
|
||||||
|
double _last_float;
|
||||||
|
string _last_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue