]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/fg_commands.cxx
Reset: clear effects cache
[flightgear.git] / src / Main / fg_commands.cxx
index 746664f2608ca7d255d1b2029d9f4bc4d51c2b7e..4c0f580b0d87051c9efe8a2927cc25835ea0a2d5 100644 (file)
@@ -23,8 +23,7 @@
 #include <simgear/structure/event_mgr.hxx>
 #include <simgear/sound/soundmgr_openal.hxx>
 #include <simgear/timing/sg_time.hxx>
-#include <simgear/misc/interpolator.hxx>
-#include <simgear/io/HTTPRequest.hxx>
+#include <simgear/io/HTTPMemoryRequest.hxx>
 
 #include <FDM/flight.hxx>
 #include <GUI/gui.h>
@@ -53,7 +52,7 @@
 
 #include <boost/scoped_array.hpp>
 
-#ifdef FG_HAVE_GPERFTOOLS
+#if FG_HAVE_GPERFTOOLS
 # include <google/profiler.h>
 #endif
 
@@ -159,7 +158,7 @@ compare_values (SGPropertyNode * value1, SGPropertyNode * value2)
 }
 
 
-\f
+
 ////////////////////////////////////////////////////////////////////////
 // Command implementations.
 ////////////////////////////////////////////////////////////////////////
@@ -235,6 +234,16 @@ do_pause (const SGPropertyNode * arg)
         fgSetBool("/sim/freeze/master",!paused);
         fgSetBool("/sim/freeze/clock",!paused);
     }
+  
+    SGPropertyNode_ptr args(new SGPropertyNode);
+    args->setStringValue("id", "sim-pause");
+    if (!paused && fgGetBool("/sim/view-name-popup")) {
+      args->setStringValue("label", "Simulation is paused");
+      globals->get_commands()->execute("show-message", args);
+    } else {
+      globals->get_commands()->execute("clear-message", args);
+    }
+  
     return true;
 }
 
@@ -366,17 +375,25 @@ do_preferences_load (const SGPropertyNode * arg)
 }
 
 static void
-do_view_next( bool )
+do_view_next(bool do_it)
 {
+  // Only switch view if really requested to do so (and not for example while
+  // reset/reposition where /command/view/next is set to false)
+  if( do_it )
+  {
     globals->get_current_view()->setHeadingOffset_deg(0.0);
     globals->get_viewmgr()->next_view();
+  }
 }
 
 static void
-do_view_prev( bool )
+do_view_prev(bool do_it)
 {
+  if( do_it )
+  {
     globals->get_current_view()->setHeadingOffset_deg(0.0);
     globals->get_viewmgr()->prev_view();
+  }
 }
 
 /**
@@ -826,7 +843,12 @@ static bool
 do_property_cycle (const SGPropertyNode * arg)
 {
     SGPropertyNode * prop = get_prop(arg);
-    vector<SGPropertyNode_ptr> values = arg->getChildren("value");
+    std::vector<SGPropertyNode_ptr> values = arg->getChildren("value");
+    
+    bool wrap = arg->getBoolValue("wrap", true);
+    // compatible with knob/pick animations
+    int offset = arg->getIntValue("offset", 1);
+    
     int selection = -1;
     int nSelections = values.size();
 
@@ -838,15 +860,22 @@ do_property_cycle (const SGPropertyNode * arg)
                                 // Try to find the current selection
     for (int i = 0; i < nSelections; i++) {
         if (compare_values(prop, values[i])) {
-            selection = i + 1;
+            selection = i;
             break;
         }
     }
 
-                                // Default or wrap to the first selection
-    if (selection < 0 || selection >= nSelections)
+    if (selection < 0) { // default to first selection
         selection = 0;
-
+    } else {
+        selection += offset;
+        if (wrap) {
+            selection = (selection + nSelections) % nSelections;
+        } else {
+            SG_CLAMP_RANGE(selection, 0, nSelections - 1);
+        }
+    }
+    
     prop->setUnspecifiedValue(values[selection]->getStringValue());
     return true;
 }
@@ -873,13 +902,15 @@ do_property_randomize (const SGPropertyNode * arg)
  * Built-in command: interpolate a property value over time
  *
  * property:        the name of the property value to interpolate.
+ * type:            the interpolation type ("numeric", "color", etc.)
+ * easing:          name of easing function (see http://easings.net/)
  * value[0..n]      any number of constant values to interpolate
  * time/rate[0..n]  time between each value, number of time elements must
  *                  match those of value elements. Instead of time also rate can
  *                  be used which automatically calculates the time to change
  *                  the property value at the given speed.
  * -or-
- * property[1..n]   any number of target values taken from named properties
+ * property[1..n+1] any number of target values taken from named properties
  * time/rate[0..n]  time between each value, number of time elements must
  *                  match those of value elements. Instead of time also rate can
  *                  be used which automatically calculates the time to change
@@ -888,63 +919,68 @@ do_property_randomize (const SGPropertyNode * arg)
 static bool
 do_property_interpolate (const SGPropertyNode * arg)
 {
-    SGPropertyNode * prop = get_prop(arg);
+  SGPropertyNode * prop = get_prop(arg);
+  if( !prop )
+    return false;
 
-    simgear::PropertyList valueNodes = arg->getChildren( "value" );
-    simgear::PropertyList timeNodes = arg->getChildren( "time" );
-    simgear::PropertyList rateNodes = arg->getChildren( "rate" );
+  simgear::PropertyList time_nodes = arg->getChildren("time");
+  simgear::PropertyList rate_nodes = arg->getChildren("rate");
 
-    if( !timeNodes.empty() && !rateNodes.empty() )
-      // mustn't specify time and rate
-      return false;
+  if( !time_nodes.empty() && !rate_nodes.empty() )
+    // mustn't specify time and rate
+    return false;
 
-    simgear::PropertyList::size_type num_times = timeNodes.empty()
-                                               ? rateNodes.size()
-                                               : timeNodes.size();
+  simgear::PropertyList::size_type num_times = time_nodes.empty()
+                                             ? rate_nodes.size()
+                                             : time_nodes.size();
 
-    boost::scoped_array<double> value;
-    boost::scoped_array<double> time;
+  simgear::PropertyList value_nodes = arg->getChildren("value");
+  if( value_nodes.empty() )
+  {
+    simgear::PropertyList prop_nodes = arg->getChildren("property");
 
-    if( valueNodes.size() > 0 ) {
-        // must match
-        if( num_times != valueNodes.size() )
-            return false;
+    // must have one more property node
+    if( prop_nodes.size() != num_times + 1 )
+      return false;
 
-        value.reset( new double[valueNodes.size()] );
-        for( simgear::PropertyList::size_type n = 0; n < valueNodes.size(); n++ ) {
-            value[n] = valueNodes[n]->getDoubleValue();
-        }
-    } else {
-        valueNodes = arg->getChildren("property");
-        // must have one more property node
-        if( valueNodes.size() - 1 != num_times )
-          return false;
+    value_nodes.reserve(num_times);
+    for( size_t i = 1; i < prop_nodes.size(); ++i )
+      value_nodes.push_back( fgGetNode(prop_nodes[i]->getStringValue()) );
+  }
 
-        value.reset( new double[valueNodes.size()-1] );
-        for( simgear::PropertyList::size_type n = 0; n < valueNodes.size()-1; n++ ) {
-            value[n] = fgGetNode(valueNodes[n+1]->getStringValue(), "/null")->getDoubleValue();
-        }
+  // must match
+  if( value_nodes.size() != num_times )
+    return false;
 
-    }
+  double_list deltas;
+  deltas.reserve(num_times);
 
-    time.reset( new double[num_times] );
-    if( !timeNodes.empty() ) {
-        for( simgear::PropertyList::size_type n = 0; n < num_times; n++ ) {
-            time[n] = timeNodes[n]->getDoubleValue();
-        }
-    } else {
-        for( simgear::PropertyList::size_type n = 0; n < num_times; n++ ) {
-            double delta = value[n]
-                         - (n > 0 ? value[n - 1] : prop->getDoubleValue());
-            time[n] = fabs(delta / rateNodes[n]->getDoubleValue());
-        }
+  if( !time_nodes.empty() )
+  {
+    for( size_t i = 0; i < num_times; ++i )
+      deltas.push_back( time_nodes[i]->getDoubleValue() );
+  }
+  else
+  {
+    for( size_t i = 0; i < num_times; ++i )
+    {
+      // TODO calculate delta based on property type
+      double delta = value_nodes[i]->getDoubleValue()
+                   - ( i > 0
+                     ? value_nodes[i - 1]->getDoubleValue()
+                     : prop->getDoubleValue()
+                     );
+      deltas.push_back( fabs(delta / rate_nodes[i]->getDoubleValue()) );
     }
+  }
 
-    ((SGInterpolator*)globals->get_subsystem_mgr()
-      ->get_group(SGSubsystemMgr::INIT)->get_subsystem("interpolator"))
-      ->interpolate(prop, num_times, value.get(), time.get() );
-
-    return true;
+  return prop->interpolate
+  (
+    arg->getStringValue("type", "numeric"),
+    value_nodes,
+    deltas,
+    arg->getStringValue("easing", "linear")
+  );
 }
 
 /**
@@ -1108,32 +1144,6 @@ do_add_model (const SGPropertyNode * arg)
     return true;
 }
 
-
-/**
- * Set mouse cursor coordinates and cursor shape.
- */
-static bool
-do_set_cursor (const SGPropertyNode * arg)
-{
-    if (arg->hasValue("x") || arg->hasValue("y")) {
-        SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
-        SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
-        int x = arg->getIntValue("x", mx->getIntValue());
-        int y = arg->getIntValue("y", my->getIntValue());
-        fgWarpMouse(x, y);
-        mx->setIntValue(x);
-        my->setIntValue(y);
-    }
-
-    SGPropertyNode *cursor = const_cast<SGPropertyNode *>(arg)->getNode("cursor", true);
-    if (cursor->getType() != simgear::props::NONE)
-        fgSetMouseCursor(cursor->getIntValue());
-
-    cursor->setIntValue(fgGetMouseCursor());
-    return true;
-}
-
-
 /**
  * Built-in command: play an audio message (i.e. a wav file) This is
  * fire and forget.  Call this once per message and it will get dumped
@@ -1154,10 +1164,11 @@ do_play_audio_sample (const SGPropertyNode * arg)
     float volume = arg->getFloatValue("volume");
     // cout << "playing " << path << " / " << file << endl;
     try {
-        static FGSampleQueue *queue = 0;
+        FGSampleQueue *queue = globals->get_chatter_queue();
         if ( !queue ) {
-           queue = new FGSampleQueue(smgr, "chatter");
-           queue->tie_to_listener();
+            queue = new FGSampleQueue(smgr, "chatter");
+            queue->tie_to_listener();
+            globals->set_chatter_queue(queue);
         }
 
         SGSoundSample *msg = new SGSoundSample(file.c_str(), path);
@@ -1282,23 +1293,18 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
     return true;
 }
 
-class RemoteXMLRequest : public simgear::HTTP::Request
+class RemoteXMLRequest:
+  public simgear::HTTP::MemoryRequest
 {
 public:
     SGPropertyNode_ptr _complete;
     SGPropertyNode_ptr _status;
     SGPropertyNode_ptr _failed;
     SGPropertyNode_ptr _target;
-    string propsData;
-    mutable string _requestBody;
-    int _requestBodyLength;
-    string _method;
-    
+
     RemoteXMLRequest(const std::string& url, SGPropertyNode* targetNode) :
-        simgear::HTTP::Request(url),
-        _target(targetNode),
-        _requestBodyLength(-1),
-        _method("GET")
+      simgear::HTTP::MemoryRequest(url),
+      _target(targetNode)
     {
     }
     
@@ -1316,54 +1322,25 @@ public:
     {
         _failed = p;
     }
-  
-    void setRequestData(const SGPropertyNode* body)
-    {
-        _method = "POST";
-        std::stringstream buf;
-        writeProperties(buf, body, true);
-        _requestBody = buf.str();
-        _requestBodyLength = _requestBody.size();
-    }
     
-    virtual std::string method() const
-    {
-        return _method;
-    }
 protected:
-    virtual int requestBodyLength() const
-    {
-        return _requestBodyLength;
-    }
     
-    virtual void getBodyData(char* s, int& count) const
+    virtual void onFail()
     {
-        int toRead = std::min(count, (int) _requestBody.size());
-        memcpy(s, _requestBody.c_str(), toRead);
-        count = toRead;
-        _requestBody = _requestBody.substr(count);
-    }
-    
-    virtual std::string requestBodyType() const
-    {
-        return "application/xml";
-    }
-    
-    virtual void gotBodyData(const char* s, int n)
-    {
-        propsData += string(s, n);
+        SG_LOG(SG_IO, SG_INFO, "network level failure in RemoteXMLRequest");
+        if (_failed) {
+            _failed->setBoolValue(true);
+        }
     }
     
-    virtual void responseComplete()
+    virtual void onDone()
     {
-        simgear::HTTP::Request::responseComplete();
-        
         int response = responseCode();
         bool failed = false;
         if (response == 200) {
             try {
-                const char* buffer = propsData.c_str();
-                readProperties(buffer, propsData.size(), _target, true);
+                const char* buffer = responseBody().c_str();
+                readProperties(buffer, responseBody().size(), _target, true);
             } catch (const sg_exception &e) {
                 SG_LOG(SG_IO, SG_WARN, "parsing XML from remote, failed: " << e.getFormattedMessage());
                 failed = true;
@@ -1375,7 +1352,7 @@ protected:
     // now the response data is output, signal Nasal / listeners
         if (_complete) _complete->setBoolValue(true);
         if (_status) _status->setIntValue(response);
-        if (_failed) _failed->setBoolValue(failed);
+        if (_failed && failed) _failed->setBoolValue(true);
     }
 };
 
@@ -1383,6 +1360,12 @@ protected:
 static bool
 do_load_xml_from_url(const SGPropertyNode * arg)
 {
+    FGHTTPClient* http = static_cast<FGHTTPClient*>(globals->get_subsystem("http"));
+    if (!http) {
+        SG_LOG(SG_IO, SG_ALERT, "xmlhttprequest: HTTP client not running");
+        return false;
+    }
+  
     std::string url(arg->getStringValue("url"));
     if (url.empty())
         return false;
@@ -1396,7 +1379,7 @@ do_load_xml_from_url(const SGPropertyNode * arg)
     RemoteXMLRequest* req = new RemoteXMLRequest(url, targetnode);
     
     if (arg->hasChild("body"))
-        req->setRequestData(arg->getChild("body"));
+        req->setBodyData(arg->getChild("body"));
     
 // connect up optional reporting properties
     if (arg->hasValue("complete")) 
@@ -1406,8 +1389,7 @@ do_load_xml_from_url(const SGPropertyNode * arg)
     if (arg->hasValue("status")) 
         req->setStatusProp(fgGetNode(arg->getStringValue("status"), true));
         
-    FGHTTPClient::instance()->makeRequest(req);
-    
+    http->makeRequest(req);
     return true;
 }
 
@@ -1505,7 +1487,7 @@ do_release_cockpit_button (const SGPropertyNode *arg)
 // Optional profiling commands using gperftools:
 // http://code.google.com/p/gperftools/
 
-#ifndef FG_HAVE_GPERFTOOLS
+#if !FG_HAVE_GPERFTOOLS
 static void
 no_profiling_support()
 {
@@ -1521,7 +1503,7 @@ no_profiling_support()
 static bool
 do_profiler_start(const SGPropertyNode *arg)
 {
-#ifdef FG_HAVE_GPERFTOOLS
+#if FG_HAVE_GPERFTOOLS
   const char *filename = arg->getStringValue("filename", "fgfs.profile");
   ProfilerStart(filename);
   return true;
@@ -1534,7 +1516,7 @@ do_profiler_start(const SGPropertyNode *arg)
 static bool
 do_profiler_stop(const SGPropertyNode *arg)
 {
-#ifdef FG_HAVE_GPERFTOOLS
+#if FG_HAVE_GPERFTOOLS
   ProfilerStop();
   return true;
 #else
@@ -1599,7 +1581,6 @@ static struct {
     { "open-browser", do_open_browser },
     { "gui-redraw", do_gui_redraw },
     { "add-model", do_add_model },
-    { "set-cursor", do_set_cursor },
     { "play-audio-sample", do_play_audio_sample },
     { "presets-commit", do_presets_commit },
     { "log-level", do_log_level },
@@ -1645,14 +1626,8 @@ fgInitCommands ()
   fgTie( "/command/view/next", dummy(0), do_view_next );
   fgTie( "/command/view/prev", dummy(0), do_view_prev );
 
-  SGPropertyNode* profiler_available =
-    globals->get_props()->getNode("/sim/debug/profiler-available", true);
-#ifdef FG_HAVE_GPERFTOOLS
-  profiler_available->setBoolValue(true);
-#else
-  profiler_available->setBoolValue(false);
-#endif
-  profiler_available->setAttributes(SGPropertyNode::READ);
+  globals->get_props()->setValueReadOnly( "/sim/debug/profiler-available",
+                                          bool(FG_HAVE_GPERFTOOLS) );
 }
 
 // end of fg_commands.cxx