]> git.mxchange.org Git - flightgear.git/commitdiff
Replace SGInterpolator with new advanced interpolation system.
authorThomas Geymayer <tomgey@gmail.com>
Sat, 16 Mar 2013 15:43:55 +0000 (16:43 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Sat, 16 Mar 2013 15:45:03 +0000 (16:45 +0100)
Allow for advanced animations using easing functions and adapters
for interpolating specific property types (eg. CSS colors).
Old behavior should not have changed.

src/Main/CMakeLists.txt
src/Main/FGInterpolator.cxx [new file with mode: 0644]
src/Main/FGInterpolator.hxx [new file with mode: 0644]
src/Main/fg_commands.cxx
src/Main/fg_init.cxx
src/Main/subsystemFactory.cxx
src/Scripting/NasalSys.cxx

index 254a44c1e152434ab50dace952a1af49f9809901..dceb3db3c7527510cf18a274bcacd3633e34b2b9 100644 (file)
@@ -14,6 +14,7 @@ set(SOURCES
        fg_io.cxx
        fg_os_common.cxx
        fg_props.cxx
+       FGInterpolator.cxx
        globals.cxx
        locale.cxx
        logger.cxx
@@ -30,6 +31,7 @@ set(HEADERS
        fg_init.hxx
        fg_io.hxx
        fg_props.hxx
+       FGInterpolator.hxx
        globals.hxx
        locale.hxx
        logger.hxx
diff --git a/src/Main/FGInterpolator.cxx b/src/Main/FGInterpolator.cxx
new file mode 100644 (file)
index 0000000..2783e0c
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * FGInterpolator.cxx
+ *
+ *  Created on: 16.03.2013
+ *      Author: tom
+ */
+
+#include "FGInterpolator.hxx"
+#include <simgear/scene/util/ColorInterpolator.hxx>
+
+//------------------------------------------------------------------------------
+FGInterpolator::FGInterpolator()
+{
+  addInterpolatorFactory<simgear::ColorInterpolator>("color");
+}
diff --git a/src/Main/FGInterpolator.hxx b/src/Main/FGInterpolator.hxx
new file mode 100644 (file)
index 0000000..ef7f621
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * FGInterpolator.hxx
+ *
+ *  Created on: 16.03.2013
+ *      Author: tom
+ */
+
+#ifndef FG_INTERPOLATOR_HXX_
+#define FG_INTERPOLATOR_HXX_
+
+#include <simgear/props/PropertyInterpolationMgr.hxx>
+
+class FGInterpolator:
+  public simgear::PropertyInterpolationMgr
+{
+  public:
+    FGInterpolator();
+};
+
+
+#endif /* FG_INTERPOLATOR_HXX_ */
index 27980afba5077834d1ac8067236b0de7d1a1dbe5..9d39d237dd883bff1ac3c177bbd710dd35287df7 100644 (file)
@@ -23,7 +23,6 @@
 #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 <FDM/flight.hxx>
@@ -45,6 +44,7 @@
 #include "fg_os.hxx"
 #include "fg_commands.hxx"
 #include "fg_props.hxx"
+#include "FGInterpolator.hxx"
 #include "globals.hxx"
 #include "logger.hxx"
 #include "util.hxx"
@@ -883,13 +883,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
@@ -898,63 +900,82 @@ do_property_randomize (const SGPropertyNode * arg)
 static bool
 do_property_interpolate (const SGPropertyNode * arg)
 {
-    SGPropertyNode * prop = get_prop(arg);
+  FGInterpolator* mgr =
+    static_cast<FGInterpolator*>
+    (
+      globals->get_subsystem_mgr()
+             ->get_group(SGSubsystemMgr::INIT)
+             ->get_subsystem("prop-interpolator")
+    );
 
-    simgear::PropertyList valueNodes = arg->getChildren( "value" );
-    simgear::PropertyList timeNodes = arg->getChildren( "time" );
-    simgear::PropertyList rateNodes = arg->getChildren( "rate" );
+  if( !mgr )
+  {
+    SG_LOG(SG_GENERAL, SG_WARN, "No property interpolator available");
+    return false;
+  }
 
-    if( !timeNodes.empty() && !rateNodes.empty() )
-      // mustn't specify time and rate
-      return false;
+  SGPropertyNode * prop = get_prop(arg);
+  simgear::PropertyList time_nodes = arg->getChildren("time");
+  simgear::PropertyList rate_nodes = arg->getChildren("rate");
 
-    simgear::PropertyList::size_type num_times = timeNodes.empty()
-                                               ? rateNodes.size()
-                                               : timeNodes.size();
+  if( !time_nodes.empty() && !rate_nodes.empty() )
+    // mustn't specify time and rate
+    return false;
 
-    boost::scoped_array<double> value;
-    boost::scoped_array<double> time;
+  simgear::PropertyList::size_type num_times = time_nodes.empty()
+                                             ? rate_nodes.size()
+                                             : time_nodes.size();
 
-    if( valueNodes.size() > 0 ) {
-        // must match
-        if( num_times != valueNodes.size() )
-            return false;
+  simgear::PropertyList value_nodes = arg->getChildren("value");
+  if( value_nodes.empty() )
+  {
+    simgear::PropertyList prop_nodes = arg->getChildren("property");
 
-        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;
+    // must have one more property node
+    if( prop_nodes.size() != num_times + 1 )
+      return false;
 
-        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();
-        }
+    value_nodes.reserve(num_times);
+    for( size_t i = 1; i < prop_nodes.size(); ++i )
+      value_nodes.push_back( fgGetNode(prop_nodes[i]->getStringValue()) );
+  }
 
-    }
+  // must match
+  if( value_nodes.size() != num_times )
+    return false;
 
-    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());
-        }
+  double_list deltas;
+  deltas.reserve(num_times);
+
+  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() );
+  mgr->interpolate
+  (
+    prop,
+    arg->getStringValue("type", "numeric"),
+    value_nodes,
+    deltas,
+    arg->getStringValue("easing", "linear")
+  );
 
-    return true;
+  return true;
 }
 
 /**
index 729301c2464d93eaa06cfd8189a584206c10b159..b0f8b511acb84900191f82f5b08d9e99ec115589 100644 (file)
@@ -51,7 +51,6 @@
 #include <simgear/misc/strutils.hxx>
 #include <simgear/props/props_io.hxx>
 
-#include <simgear/misc/interpolator.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/model/particles.hxx>
 
 #include "fg_io.hxx"
 #include "fg_commands.hxx"
 #include "fg_props.hxx"
+#include "FGInterpolator.hxx"
 #include "options.hxx"
 #include "globals.hxx"
 #include "logger.hxx"
@@ -570,7 +570,9 @@ void fgCreateSubsystems() {
     // Initialize the property interpolator subsystem. Put into the INIT
     // group because the "nasal" subsystem may need it at GENERAL take-down.
     ////////////////////////////////////////////////////////////////////
-    globals->add_subsystem("interpolator", new SGInterpolator, SGSubsystemMgr::INIT);
+    globals->add_subsystem( "prop-interpolator",
+                            new FGInterpolator,
+                            SGSubsystemMgr::INIT );
 
 
     ////////////////////////////////////////////////////////////////////
index c174ad5fb349aa66ad296adbb2c6dfeb6c2e22a8..3931a6c8ef50461712dba644b8a6c8b499a057e8 100644 (file)
@@ -33,8 +33,8 @@
 
 // subsystem includes
 #include <Aircraft/controls.hxx>
-#include <simgear/misc/interpolator.hxx>
 #include <Main/fg_props.hxx>
+#include <Main/FGInterpolator.hxx>
 #include <Main/fg_io.hxx>
 #include <FDM/fdm_shell.hxx>
 #include <Environment/environment_mgr.hxx>
@@ -76,7 +76,7 @@ SGSubsystem* createSubsystemByName(const std::string& name)
     
     MAKE_SUB(FGControls, "controls");  
     MAKE_SUB(FGSoundManager, "sound");
-    MAKE_SUB(SGInterpolator, "interpolator");
+    MAKE_SUB(FGInterpolator, "prop-interpolator")
     MAKE_SUB(FGProperties, "properties");
     MAKE_SUB(FDMShell, "fdm");
     MAKE_SUB(FGEnvironmentMgr, "environment");
index f7a1cbd38a927923867751a0fee1faa4306d517f..58a9417dc5ebb65c7264447a36a740a662884ea9 100644 (file)
@@ -23,7 +23,6 @@
 #include <simgear/math/sg_random.h>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sg_dir.hxx>
-#include <simgear/misc/interpolator.hxx>
 #include <simgear/structure/commands.hxx>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/structure/event_mgr.hxx>
@@ -46,7 +45,7 @@
 #include <Main/globals.hxx>
 #include <Main/util.hxx>
 #include <Main/fg_props.hxx>
-
+#include <Main/FGInterpolator.hxx>
 
 using std::map;
 
@@ -514,29 +513,52 @@ static naRef f_cmdarg(naContext c, naRef me, int argc, naRef* args)
 // value/delta numbers.
 static naRef f_interpolate(naContext c, naRef me, int argc, naRef* args)
 {
-    SGPropertyNode* node;
-    naRef prop = argc > 0 ? args[0] : naNil();
-    if(naIsString(prop)) node = fgGetNode(naStr_data(prop), true);
-    else if(naIsGhost(prop)) node = *(SGPropertyNode_ptr*)naGhost_ptr(prop);
-    else return naNil();
-
-    naRef curve = argc > 1 ? args[1] : naNil();
-    if(!naIsVector(curve)) return naNil();
-    int nPoints = naVec_size(curve) / 2;
-    double* values = new double[nPoints];
-    double* deltas = new double[nPoints];
-    for(int i=0; i<nPoints; i++) {
-        values[i] = naNumValue(naVec_get(curve, 2*i)).num;
-        deltas[i] = naNumValue(naVec_get(curve, 2*i+1)).num;
-    }
+  FGInterpolator* mgr =
+    static_cast<FGInterpolator*>
+    (
+      globals->get_subsystem_mgr()
+             ->get_group(SGSubsystemMgr::INIT)
+             ->get_subsystem("prop-interpolator")
+    );
+  if( !mgr )
+  {
+    SG_LOG(SG_GENERAL, SG_WARN, "No property interpolator available");
+    return naNil();
+  };
 
-    ((SGInterpolator*)globals->get_subsystem_mgr()
-        ->get_group(SGSubsystemMgr::INIT)->get_subsystem("interpolator"))
-        ->interpolate(node, nPoints, values, deltas);
+  SGPropertyNode* node;
+  naRef prop = argc > 0 ? args[0] : naNil();
+  if(naIsString(prop)) node = fgGetNode(naStr_data(prop), true);
+  else if(naIsGhost(prop)) node = *(SGPropertyNode_ptr*)naGhost_ptr(prop);
+  else return naNil();
 
-    delete[] values;
-    delete[] deltas;
-    return naNil();
+  naRef curve = argc > 1 ? args[1] : naNil();
+  if(!naIsVector(curve)) return naNil();
+  int nPoints = naVec_size(curve) / 2;
+
+  simgear::PropertyList value_nodes;
+  value_nodes.reserve(nPoints);
+  double_list deltas;
+  deltas.reserve(nPoints);
+
+  for( int i = 0; i < nPoints; ++i )
+  {
+    SGPropertyNode* val = new SGPropertyNode;
+    val->setDoubleValue(naNumValue(naVec_get(curve, 2*i)).num);
+    value_nodes.push_back(val);
+    deltas.push_back(naNumValue(naVec_get(curve, 2*i+1)).num);
+  }
+
+  mgr->interpolate
+  (
+    node,
+    "numeric",
+    value_nodes,
+    deltas,
+    "linear"
+  );
+
+  return naNil();
 }
 
 // This is a better RNG than the one in the default Nasal distribution