]> git.mxchange.org Git - flightgear.git/commitdiff
add new listener type: setlistner(<prop>, <func> [, <type=0>]);
authormfranz <mfranz>
Fri, 12 Oct 2007 17:24:43 +0000 (17:24 +0000)
committermfranz <mfranz>
Fri, 12 Oct 2007 17:24:43 +0000 (17:24 +0000)
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

src/Scripting/NasalSys.cxx
src/Scripting/NasalSys.hxx

index 7811895b2bcad71c1b300bb7d1681f68a4afb74a..ac5c98d1d34cc5665b22f31b2bb3c764d984c562 100644 (file)
@@ -896,8 +896,9 @@ int FGNasalSys::_listenerId = 0;
 
 // setlistener(property, func, bool) extension function.  The first argument
 // is either a ghost (SGPropertyNode_ptr*) or a string (global property
-// path), the second is a Nasal function, the optional third one a bool.
-// If the bool is true, then the listener is executed initially. The
+// path), the second is a Nasal function, the optional third one an integer.
+// 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
 // as argument to the removelistener() function.
 naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
@@ -921,11 +922,10 @@ naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
         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,
-            gcSave(handler), _listenerId);
-    node->addChangeListener(nl, initial);
+            gcSave(handler), _listenerId, type);
+    node->addChangeListener(nl, type != 0);
 
     _listener[_listenerId] = nl;
     return naNum(_listenerId++);
@@ -960,15 +960,21 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
 // FGNasalListener class.
 
 FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
-                                 FGNasalSys* nasal, int key, int id) :
+                                 FGNasalSys* nasal, int key, int id,
+                                 int type) :
     _node(node),
     _handler(handler),
     _gcKey(key),
     _id(id),
+    _type(type),
     _nas(nasal),
     _active(0),
-    _dead(false)
+    _dead(false),
+    _first_call(true),
+    _last_int(0L),
+    _last_float(0.0)
 {
+    unchanged(node);
 }
 
 FGNasalListener::~FGNasalListener()
@@ -982,14 +988,51 @@ void FGNasalListener::valueChanged(SGPropertyNode* node)
     // drop recursive listener calls
     if(_active || _dead)
         return;
+    if(_type == 2 && !_first_call && unchanged(node))
+        return;
 
     SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
     _active++;
     _nas->_cmdArg = node;
     _nas->call(_handler, naNil());
     _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;
+        }
+    }
+}
 
 
 
index a68317570842fd9fcae58f6b78488c5e701491ce..0e46e9f2034ad358361c8c3cd5bc5d46b3dd1fb2 100644 (file)
@@ -132,10 +132,11 @@ private:
 class FGNasalListener : public SGPropertyChangeListener {
 public:
     FGNasalListener(SGPropertyNode_ptr node, naRef handler,
-                    FGNasalSys* nasal, int key, int id);
+                    FGNasalSys* nasal, int key, int id, int type);
 
     ~FGNasalListener();
     void valueChanged(SGPropertyNode* node);
+    bool unchanged(SGPropertyNode* node);
 
 private:
     friend class FGNasalSys;
@@ -143,9 +144,14 @@ private:
     naRef _handler;
     int _gcKey;
     int _id;
+    int _type;
     FGNasalSys* _nas;
     unsigned int _active;
     bool _dead;
+    bool _first_call;
+    long _last_int;
+    double _last_float;
+    string _last_string;
 };