From 3d2a74a6529782ce95049a8b6129c56d49423e0e Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Fri, 4 May 2018 22:31:25 +0200 Subject: [PATCH] Ref T261, interpolator mode is now part of setup * added attribute in setup * adjusted UI * adjusted interpolator / simulator functions --- src/blackcore/simulator.h | 4 - src/blackcore/simulatorcommon.cpp | 21 ++++- .../interpolationsetupcomponent.cpp | 21 ++++- .../editors/interpolationsetupform.cpp | 14 ++++ src/blackgui/editors/interpolationsetupform.h | 3 + .../editors/interpolationsetupform.ui | 52 +++++++----- .../interpolationrenderingsetup.cpp | 32 +++++++- .../simulation/interpolationrenderingsetup.h | 31 ++++++- .../simulation/interpolatormulti.cpp | 80 ++++--------------- src/blackmisc/simulation/interpolatormulti.h | 31 +------ .../simulator/emulated/simulatoremulated.cpp | 8 -- .../simulator/emulated/simulatoremulated.h | 1 - src/plugins/simulator/fs9/simulatorfs9.cpp | 10 --- .../simulator/fsxcommon/simconnectobject.cpp | 44 +--------- .../simulator/fsxcommon/simconnectobject.h | 16 +--- .../fsxcommon/simulatorfsxcommon.cpp | 21 +---- .../simulator/fsxcommon/simulatorfsxcommon.h | 1 - .../simulator/xplane/simulatorxplane.cpp | 17 ---- .../simulator/xplane/simulatorxplane.h | 1 - .../simulator/xplane/xplanempaircraft.cpp | 26 +----- .../simulator/xplane/xplanempaircraft.h | 11 +-- 21 files changed, 175 insertions(+), 270 deletions(-) diff --git a/src/blackcore/simulator.h b/src/blackcore/simulator.h index 1517fb125..cccd953b7 100644 --- a/src/blackcore/simulator.h +++ b/src/blackcore/simulator.h @@ -187,10 +187,6 @@ namespace BlackCore //! \copydoc BlackMisc::IProvider::asQObject virtual QObject *asQObject() override { return this; } - //! Set interpolation mode, empty callsign applies to all know callsigns - //! \return Returns true if the mode changed, otherwise false. Note that some implementations always return true. - virtual bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode, const BlackMisc::Aviation::CCallsign &callsign) = 0; - //! \addtogroup swiftdotcommands //! @{ //!
diff --git a/src/blackcore/simulatorcommon.cpp b/src/blackcore/simulatorcommon.cpp
index 4f611c08f..f5a961dc8 100644
--- a/src/blackcore/simulatorcommon.cpp
+++ b/src/blackcore/simulatorcommon.cpp
@@ -477,10 +477,23 @@ namespace BlackCore
 
         if (part1.startsWith("spline") || part1.startsWith("linear"))
         {
-            const CCallsign cs(parser.hasPart(2) ? parser.part(2) : "");
-            const bool changed = this->setInterpolatorMode(CInterpolatorMulti::modeFromString(part1), cs);
-            CLogMessage(this).info(changed ? "Changed interpolation mode" : "Unchanged interpolation mode");
-            return true;
+            if (parser.hasPart(2))
+            {
+                const CCallsign cs(parser.part(2));
+                CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupPerCallsignOrDefault(cs);
+                const bool changed = setup.setInterpolatorMode(part1);
+                if (changed) { this->setInterpolationSetupPerCallsign(setup, cs); }
+                CLogMessage(this).info(changed ? "Changed interpolation mode for '%1'" : "Unchanged interpolation mode for '%1'") << cs.asString();
+                return true;
+            }
+            else
+            {
+                CInterpolationAndRenderingSetupGlobal setup = this->getInterpolationSetupGlobal();
+                const bool changed = setup.setInterpolatorMode(part1);
+                if (changed) { this->setInterpolationAndRenderingSetup(setup); }
+                CLogMessage(this).info(changed ? "Changed interpolation mode globally" : "Unchanged interpolation mode");
+                return true;
+            }
         } // spline/linear
 
         if (part1.startsWith("pos"))
diff --git a/src/blackgui/components/interpolationsetupcomponent.cpp b/src/blackgui/components/interpolationsetupcomponent.cpp
index 428f598da..111fd0e1f 100644
--- a/src/blackgui/components/interpolationsetupcomponent.cpp
+++ b/src/blackgui/components/interpolationsetupcomponent.cpp
@@ -14,6 +14,7 @@
 #include "blackcore/context/contextsimulator.h"
 #include "blackmisc/simulation/interpolationsetuplist.h"
 #include "blackmisc/statusmessage.h"
+#include 
 
 using namespace BlackGui::Views;
 using namespace BlackMisc;
@@ -41,7 +42,13 @@ namespace BlackGui
             connect(ui->rb_Global, &QRadioButton::released, this, &CInterpolationSetupComponent::onModeChanged);
 
             ui->rb_Global->setChecked(true);
-            QTimer::singleShot(250, this, &CInterpolationSetupComponent::onModeChanged);
+
+            QPointer myself(this);
+            QTimer::singleShot(250, this, [ = ]
+            {
+                if (myself.isNull()) { return; }
+                this->onModeChanged();
+            });
         }
 
         CInterpolationSetupComponent::~CInterpolationSetupComponent()
@@ -118,7 +125,13 @@ namespace BlackGui
             if (removed < 1) { return; } // nothing done
             const bool set = this->setSetupsToContext(setups);
             if (!set) { return; }
-            QTimer::singleShot(100, this, &CInterpolationSetupComponent::displaySetupsPerCallsign);
+
+            QPointer myself(this);
+            QTimer::singleShot(100, this, [ = ]
+            {
+                if (myself.isNull()) { return; }
+                this->displaySetupsPerCallsign();
+            });
         }
 
         void CInterpolationSetupComponent::setUiValuesFromGlobal()
@@ -137,7 +150,7 @@ namespace BlackGui
 
         bool CInterpolationSetupComponent::checkPrerequisites()
         {
-            if (!sGui || !sGui->getIContextSimulator())
+            if (!sGui || !sGui->getIContextSimulator() || sGui->isShuttingDown())
             {
                 const CStatusMessage m = CStatusMessage(this).validationError("No context");
                 this->showOverlayMessage(m);
@@ -154,7 +167,7 @@ namespace BlackGui
 
         bool CInterpolationSetupComponent::setSetupsToContext(const CInterpolationSetupList &setups)
         {
-            if (!sGui || !sGui->getIContextSimulator()) { return false; }
+            if (!sGui || sGui->isShuttingDown() || !sGui->getIContextSimulator()) { return false; }
             if (setups == m_lastSetSetups) { return false; }
             sGui->getIContextSimulator()->setInterpolationAndRenderingSetupsPerCallsign(setups);
             m_lastSetSetups = setups;
diff --git a/src/blackgui/editors/interpolationsetupform.cpp b/src/blackgui/editors/interpolationsetupform.cpp
index fb33c85e8..8528aa2ed 100644
--- a/src/blackgui/editors/interpolationsetupform.cpp
+++ b/src/blackgui/editors/interpolationsetupform.cpp
@@ -28,6 +28,8 @@ namespace BlackGui
             {
                 connect(cb, &QCheckBox::stateChanged, this, &CInterpolationSetupForm::onCheckboxChanged);
             }
+
+            connect(ui->co_InterpolatorMode, &QComboBox::currentTextChanged, this, &CInterpolationSetupForm::onInterpolatorModeChanged);
         }
 
         CInterpolationSetupForm::~CInterpolationSetupForm()
@@ -41,6 +43,10 @@ namespace BlackGui
             ui->cb_ForceFullInterpolation->setChecked(setup.isForcingFullInterpolation());
             ui->cb_EnableGndFlag->setChecked(setup.isGndFlagEnabled());
             ui->cb_SendGndFlagToSim->setChecked(setup.sendGndFlagToSimulator());
+
+            const QString im = setup.getInterpolatorModeAsString();
+            if (im.contains("linear", Qt::CaseInsensitive)) { ui->co_InterpolatorMode->setCurrentIndex(1); }
+            else { ui->co_InterpolatorMode->setCurrentIndex(0); }
         }
 
         CInterpolationAndRenderingSetupPerCallsign CInterpolationSetupForm::getValue() const
@@ -52,6 +58,7 @@ namespace BlackGui
             setup.setLogInterpolation(ui->cb_LogInterpolation->isChecked());
             setup.setSendGndFlagToSimulator(ui->cb_SendGndFlagToSim->isChecked());
             setup.setSimulatorDebuggingMessages(ui->cb_DebugDriver->isChecked());
+            setup.setInterpolatorMode(ui->co_InterpolatorMode->currentText());
             return setup;
         }
 
@@ -63,6 +70,7 @@ namespace BlackGui
             CGuiUtility::checkBoxReadOnly(ui->cb_ForceFullInterpolation, readonly);
             CGuiUtility::checkBoxReadOnly(ui->cb_EnableGndFlag, readonly);
             CGuiUtility::checkBoxReadOnly(ui->cb_SendGndFlagToSim, readonly);
+            ui->co_InterpolatorMode->setEnabled(!readonly);
         }
 
         CStatusMessageList CInterpolationSetupForm::validate(bool nested) const
@@ -76,5 +84,11 @@ namespace BlackGui
             Q_UNUSED(state);
             emit this->valueChanged();
         }
+
+        void CInterpolationSetupForm::onInterpolatorModeChanged(const QString &mode)
+        {
+            Q_UNUSED(mode);
+            emit this->valueChanged();
+        }
     } // ns
 } // ns
diff --git a/src/blackgui/editors/interpolationsetupform.h b/src/blackgui/editors/interpolationsetupform.h
index 0be237a1b..ba6436f69 100644
--- a/src/blackgui/editors/interpolationsetupform.h
+++ b/src/blackgui/editors/interpolationsetupform.h
@@ -58,6 +58,9 @@ namespace BlackGui
 
             //! Checkbox has been changed
             void onCheckboxChanged(int state);
+
+            //! Interpolator mode
+            void onInterpolatorModeChanged(const QString &mode);
         };
     } // ns
 } // ns
diff --git a/src/blackgui/editors/interpolationsetupform.ui b/src/blackgui/editors/interpolationsetupform.ui
index e42da8111..367a1d5a6 100644
--- a/src/blackgui/editors/interpolationsetupform.ui
+++ b/src/blackgui/editors/interpolationsetupform.ui
@@ -7,21 +7,35 @@
     0
     0
     236
-    75
+    102
    
   
   
    Frame
   
   
-   
+   
+    
+     
+      force full interpolation
+     
+    
+   
+   
+    
+     
+      driver dbg. msgs.
+     
+    
+   
+   
     
      
       use gnd.flag
      
     
    
-   
+   
     
      
       enable parts
@@ -31,34 +45,34 @@
      
     
    
-   
-    
-     
-      force full interpolation
-     
-    
-   
-   
-    
-     
-      driver dbg. msgs.
-     
-    
-   
-   
+   
     
      
       log.interpolation
      
     
    
-   
+   
     
      
       send gnd.to simulator
      
     
    
+   
+    
+     
+      
+       Spline interpolator
+      
+     
+     
+      
+       Linear interpolator
+      
+     
+    
+   
   
  
  
diff --git a/src/blackmisc/simulation/interpolationrenderingsetup.cpp b/src/blackmisc/simulation/interpolationrenderingsetup.cpp
index e32306b2d..43654a491 100644
--- a/src/blackmisc/simulation/interpolationrenderingsetup.cpp
+++ b/src/blackmisc/simulation/interpolationrenderingsetup.cpp
@@ -41,7 +41,34 @@ namespace BlackMisc
         void CInterpolationAndRenderingSetupBase::consolidateWithClient(const CClient &client)
         {
             m_enabledAircraftParts &= client.hasAircraftPartsCapability();
-            // m_enabledGndFlag &= client.hasGndFlagCapability();
+        }
+
+        bool CInterpolationAndRenderingSetupBase::setInterpolatorMode(CInterpolationAndRenderingSetupBase::InterpolatorMode mode)
+        {
+            const int m = static_cast(mode);
+            if (m_interpolatorMode == m) { return false; }
+            m_interpolatorMode = m;
+            return true;
+        }
+
+        bool CInterpolationAndRenderingSetupBase::setInterpolatorMode(const QString &mode)
+        {
+            if (mode.contains("spline", Qt::CaseInsensitive)) { return this->setInterpolatorMode(Spline); }
+            if (mode.contains("linear", Qt::CaseInsensitive)) { return this->setInterpolatorMode(Linear); }
+            return false;
+        }
+
+        const QString &CInterpolationAndRenderingSetupBase::modeToString(InterpolatorMode mode)
+        {
+            static const QString l("linear");
+            static const QString s("spline");
+
+            switch (mode)
+            {
+            case Linear: return l;
+            case Spline: return s;
+            default: return s;
+            }
         }
 
         bool CInterpolationAndRenderingSetupBase::setEnabledAircraftParts(bool enabled)
@@ -94,7 +121,8 @@ namespace BlackMisc
         {
             Q_UNUSED(i18n);
             return
-                QStringLiteral("Dbg.sim.msgs: ") % boolToYesNo(m_simulatorDebugMessages) %
+                QStringLiteral("Interpolator: ") % this->getInterpolatorModeAsString() %
+                QStringLiteral(" | Dbg.sim.msgs: ") % boolToYesNo(m_simulatorDebugMessages) %
                 QStringLiteral(" | log interpolation: ") % boolToYesNo(m_logInterpolation) %
                 QStringLiteral(" | force full interpolation: ") % boolToYesNo(m_forceFullInterpolation) %
                 QStringLiteral(" | enable parts: ") % boolToYesNo(m_enabledAircraftParts) %
diff --git a/src/blackmisc/simulation/interpolationrenderingsetup.h b/src/blackmisc/simulation/interpolationrenderingsetup.h
index 3f40bbe1e..e46c80476 100644
--- a/src/blackmisc/simulation/interpolationrenderingsetup.h
+++ b/src/blackmisc/simulation/interpolationrenderingsetup.h
@@ -36,7 +36,15 @@ namespace BlackMisc
                 IndexForceFullInterpolation,
                 IndexSendGndFlagToSimulator,
                 IndexEnableGndFlag,
-                IndexEnabledAircraftParts
+                IndexEnabledAircraftParts,
+                IndexInterpolatorMode
+            };
+
+            //! Interpolator type
+            enum InterpolatorMode
+            {
+                Spline,
+                Linear
             };
 
             //! Debugging messages for simulation
@@ -81,6 +89,18 @@ namespace BlackMisc
             //! Consolidate with a network client
             void consolidateWithClient(const Network::CClient &client);
 
+            //! Interpolator mode
+            InterpolatorMode getInterpolatorMode() const { return static_cast(m_interpolatorMode);  }
+
+            //! Interpolator mode
+            const QString &getInterpolatorModeAsString() const { return modeToString(this->getInterpolatorMode()); }
+
+            //! Set interpolator mode
+            bool setInterpolatorMode(InterpolatorMode mode);
+
+            //! Set interpolator mode
+            bool setInterpolatorMode(const QString &mode);
+
             //! \copydoc BlackMisc::Mixin::String::toQString
             QString convertToQString(bool i18n = false) const;
 
@@ -90,6 +110,9 @@ namespace BlackMisc
             //! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
             void setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant);
 
+            //! Interpolator mode as string
+            static const QString &modeToString(InterpolatorMode mode);
+
         protected:
             //! Constructor
             CInterpolationAndRenderingSetupBase();
@@ -103,6 +126,7 @@ namespace BlackMisc
             bool m_enabledAircraftParts   = true;  //!< Enable aircraft parts
             bool m_enabledGndFlag         = true;  //!< Enable gnd.flag
             bool m_sendGndToSim           = true;  //!< Send the gnd.flag to simulator
+            int  m_interpolatorMode       = static_cast(Spline); //!< interpolator mode (spline, ...)
         };
 
         //! Value object for interpolator and rendering
@@ -184,6 +208,7 @@ namespace BlackMisc
                 BLACK_METAMEMBER(sendGndToSim),
                 BLACK_METAMEMBER(enabledAircraftParts),
                 BLACK_METAMEMBER(enabledGndFlag),
+                BLACK_METAMEMBER(interpolatorMode),
                 BLACK_METAMEMBER(maxRenderedAircraft),
                 BLACK_METAMEMBER(maxRenderedDistance)
             );
@@ -241,7 +266,8 @@ namespace BlackMisc
                 BLACK_METAMEMBER(forceFullInterpolation),
                 BLACK_METAMEMBER(sendGndToSim),
                 BLACK_METAMEMBER(enabledAircraftParts),
-                BLACK_METAMEMBER(enabledGndFlag)
+                BLACK_METAMEMBER(enabledGndFlag),
+                BLACK_METAMEMBER(interpolatorMode)
             );
         };
     } // namespace
@@ -249,5 +275,6 @@ namespace BlackMisc
 
 Q_DECLARE_METATYPE(BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign)
 Q_DECLARE_METATYPE(BlackMisc::Simulation::CInterpolationAndRenderingSetupGlobal)
+Q_DECLARE_METATYPE(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode)
 
 #endif // guard
diff --git a/src/blackmisc/simulation/interpolatormulti.cpp b/src/blackmisc/simulation/interpolatormulti.cpp
index d00480d74..5c3f4970b 100644
--- a/src/blackmisc/simulation/interpolatormulti.cpp
+++ b/src/blackmisc/simulation/interpolatormulti.cpp
@@ -26,10 +26,10 @@ namespace BlackMisc
                 const CInterpolationAndRenderingSetupPerCallsign &setup,
                 CInterpolationStatus &status)
         {
-            switch (m_mode)
+            switch (setup.getInterpolatorMode())
             {
-            case ModeLinear: return m_linear.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
-            case ModeSpline: return m_spline.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
+            case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
+            case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
             default: break;
             }
             return {};
@@ -39,11 +39,11 @@ namespace BlackMisc
             qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
             CPartsStatus &partsStatus, bool log) const
         {
-            switch (m_mode)
+            switch (setup.getInterpolatorMode())
             {
             // currently calls the same interpolation for parts
-            case ModeLinear: return m_linear.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
-            case ModeSpline: return m_spline.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
+            case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
+            case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
             default: break;
             }
             return {};
@@ -53,22 +53,22 @@ namespace BlackMisc
             qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
             CPartsStatus &partsStatus, bool log) const
         {
-            switch (m_mode)
+            switch (setup.getInterpolatorMode())
             {
             // currently calls the same interpolation for parts
-            case ModeLinear: return m_linear.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
-            case ModeSpline: return m_spline.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
+            case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
+            case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
             default: break;
             }
             return {};
         }
 
-        const CAircraftSituation &CInterpolatorMulti::getLastInterpolatedSituation() const
+        const CAircraftSituation &CInterpolatorMulti::getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
         {
-            switch (m_mode)
+            switch (mode)
             {
-            case ModeLinear: return m_linear.getLastInterpolatedSituation();
-            case ModeSpline: return m_spline.getLastInterpolatedSituation();
+            case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getLastInterpolatedSituation();
+            case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getLastInterpolatedSituation();
             default: break;
             }
             return CAircraftSituation::null();
@@ -86,63 +86,17 @@ namespace BlackMisc
             m_spline.initCorrespondingModel(model);
         }
 
-        bool CInterpolatorMulti::setMode(Mode mode)
+        QString CInterpolatorMulti::getInterpolatorInfo(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
         {
-            if (m_mode == mode) { return false; }
-            m_mode = mode;
-            return true;
-        }
-
-        bool CInterpolatorMulti::setMode(const QString &mode)
-        {
-            Mode m = modeFromString(mode);
-            if (m == ModeUnknown) { return false; }
-            return setMode(m);
-        }
-
-        void CInterpolatorMulti::toggleMode()
-        {
-            switch (m_mode)
+            switch (mode)
             {
-            case ModeSpline: m_mode = ModeLinear; break;
-            case ModeLinear: m_mode = ModeSpline; break;
-            default: m_mode = ModeSpline; break;
-            }
-        }
-
-        QString CInterpolatorMulti::getInterpolatorInfo() const
-        {
-            switch (m_mode)
-            {
-            case ModeSpline: return m_spline.getInterpolatorInfo();
-            case ModeLinear: return m_linear.getInterpolatorInfo();
+            case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatorInfo();
+            case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatorInfo();
             default: break;
             }
             return ("Illegal mode");
         }
 
-        CInterpolatorMulti::Mode CInterpolatorMulti::modeFromString(const QString &mode)
-        {
-            if (mode.contains("spli"), Qt::CaseInsensitive) { return ModeSpline; }
-            if (mode.contains("lin"), Qt::CaseInsensitive) { return ModeLinear; }
-            return ModeUnknown;
-        }
-
-        const QString &CInterpolatorMulti::modeToString(CInterpolatorMulti::Mode mode)
-        {
-            static const QString l("linear");
-            static const QString s("spline");
-            static const QString u("unknown");
-
-            switch (mode)
-            {
-            case ModeLinear: return l;
-            case ModeSpline: return s;
-            case ModeUnknown:
-            default: return u;
-            }
-        }
-
         CInterpolatorMultiWrapper::CInterpolatorMultiWrapper()
         { }
 
diff --git a/src/blackmisc/simulation/interpolatormulti.h b/src/blackmisc/simulation/interpolatormulti.h
index da8a45c8c..da1a61739 100644
--- a/src/blackmisc/simulation/interpolatormulti.h
+++ b/src/blackmisc/simulation/interpolatormulti.h
@@ -44,7 +44,7 @@ namespace BlackMisc
                 CPartsStatus &partsStatus, bool log) const;
 
             //! \copydoc CInterpolator::getLastInterpolatedSituation
-            const Aviation::CAircraftSituation &getLastInterpolatedSituation() const;
+            const Aviation::CAircraftSituation &getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
 
             //! \copydoc CInterpolator::attachLogger
             void attachLogger(CInterpolationLogger *logger);
@@ -52,37 +52,10 @@ namespace BlackMisc
             //! \copydoc CInterpolator::initCorrespondingModel
             void initCorrespondingModel(const CAircraftModel &model);
 
-            //! Supported interpolation modes.
-            enum Mode
-            {
-                ModeSpline, //!< spline interpolation mode
-                ModeLinear, //!< linear interpolation mode
-                ModeUnknown
-            };
-
-            //! Set interpolation mode. Return true if mode was changed. Mode will not be changed in release build.
-            bool setMode(Mode mode);
-
-            //! Set interpolation mode. Return true if mode was changed. Mode will not be changed in release build.
-            bool setMode(const QString &mode);
-
-            //! Get active interpolation mode.
-            Mode getMode() const { return m_mode; }
-
-            //! Toogle interpolator Mode
-            void toggleMode();
-
             //! Info string
-            QString getInterpolatorInfo() const;
-
-            //! Mode from string
-            static Mode modeFromString(const QString &mode);
-
-            //! Mode to string
-            static const QString &modeToString(Mode mode);
+            QString getInterpolatorInfo(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
 
         private:
-            Mode m_mode = ModeSpline;
             CInterpolatorSpline m_spline;
             CInterpolatorLinear m_linear;
         };
diff --git a/src/plugins/simulator/emulated/simulatoremulated.cpp b/src/plugins/simulator/emulated/simulatoremulated.cpp
index 832f25d47..5e8b4fad7 100644
--- a/src/plugins/simulator/emulated/simulatoremulated.cpp
+++ b/src/plugins/simulator/emulated/simulatoremulated.cpp
@@ -303,14 +303,6 @@ namespace BlackSimPlugin
             return c > 0;
         }
 
-        bool CSimulatorEmulated::setInterpolatorMode(CInterpolatorMulti::Mode mode, const CCallsign &callsign)
-        {
-            if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, CInterpolatorMulti::modeToString(mode), callsign.toQString());
-            if (!m_interpolators.contains(callsign)) { return false; }
-            CInterpolatorMulti *im = m_interpolators[callsign];
-            return im->setMode(mode);
-        }
-
         int CSimulatorEmulated::physicallyRemoveAllRemoteAircraft()
         {
             if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO);
diff --git a/src/plugins/simulator/emulated/simulatoremulated.h b/src/plugins/simulator/emulated/simulatoremulated.h
index cd0f13f35..7bff81d55 100644
--- a/src/plugins/simulator/emulated/simulatoremulated.h
+++ b/src/plugins/simulator/emulated/simulatoremulated.h
@@ -60,7 +60,6 @@ namespace BlackSimPlugin
             virtual BlackMisc::PhysicalQuantities::CTime getTimeSynchronizationOffset() const override;
             virtual bool isPhysicallyRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) const override;
             virtual BlackMisc::Aviation::CCallsignSet physicallyRenderedAircraft() const override;
-            virtual bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode, const BlackMisc::Aviation::CCallsign &callsign) override;
 
             // functions just logged
             virtual void highlightAircraft(const BlackMisc::Simulation::CSimulatedAircraft &aircraftToHighlight, bool enableHighlight, const BlackMisc::PhysicalQuantities::CTime &displayTime) override;
diff --git a/src/plugins/simulator/fs9/simulatorfs9.cpp b/src/plugins/simulator/fs9/simulatorfs9.cpp
index 9615c8180..a39d2b120 100644
--- a/src/plugins/simulator/fs9/simulatorfs9.cpp
+++ b/src/plugins/simulator/fs9/simulatorfs9.cpp
@@ -279,16 +279,6 @@ namespace BlackSimPlugin
             this->displayStatusMessage(message.asStatusMessage(true, true));
         }
 
-        bool CSimulatorFs9::setInterpolatorMode(CInterpolatorMulti::Mode mode, const CCallsign &callsign)
-        {
-            const auto it = m_hashFs9Clients.find(callsign);
-            if (it == m_hashFs9Clients.end()) { return false; }
-            QTimer::singleShot(0, it->data(), [client = *it, mode] { client->getInterpolator()->setMode(mode); });
-            // Always return true if we were setting the mode, since we cannot easily access the return value from
-            // CInterpolatorMulti::setMode in a thread safe manner.
-            return true;
-        }
-
         bool CSimulatorFs9::isPhysicallyRenderedAircraft(const CCallsign &callsign) const
         {
             return m_hashFs9Clients.contains(callsign);
diff --git a/src/plugins/simulator/fsxcommon/simconnectobject.cpp b/src/plugins/simulator/fsxcommon/simconnectobject.cpp
index 77efc04a5..86c681330 100644
--- a/src/plugins/simulator/fsxcommon/simconnectobject.cpp
+++ b/src/plugins/simulator/fsxcommon/simconnectobject.cpp
@@ -106,22 +106,10 @@ namespace BlackSimPlugin
             return this->hasValidRequestId() && this->hasValidObjectId();
         }
 
-        void CSimConnectObject::toggleInterpolatorMode()
+        QString CSimConnectObject::getInterpolatorInfo(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
         {
             Q_ASSERT(m_interpolator);
-            m_interpolator->toggleMode();
-        }
-
-        bool CSimConnectObject::setInterpolatorMode(CInterpolatorMulti::Mode mode)
-        {
-            Q_ASSERT(m_interpolator);
-            return m_interpolator->setMode(mode);
-        }
-
-        QString CSimConnectObject::getInterpolatorInfo() const
-        {
-            Q_ASSERT(m_interpolator);
-            return m_interpolator->getInterpolatorInfo();
+            return m_interpolator->getInterpolatorInfo(mode);
         }
 
         void CSimConnectObject::attachInterpolatorLogger(CInterpolationLogger *logger)
@@ -157,10 +145,10 @@ namespace BlackSimPlugin
             return m_interpolator->getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
         }
 
-        const CAircraftSituation &CSimConnectObject::getLastInterpolatedSituation() const
+        const CAircraftSituation &CSimConnectObject::getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
         {
             if (!m_interpolator) { return CAircraftSituation::null(); }
-            return m_interpolator->getLastInterpolatedSituation();
+            return m_interpolator->getLastInterpolatedSituation(mode);
         }
 
         bool CSimConnectObjects::setSimConnectObjectIdForRequestId(DWORD requestId, DWORD objectId, bool resetSentParts)
@@ -324,29 +312,5 @@ namespace BlackSimPlugin
             }
             return false;
         }
-
-        void CSimConnectObjects::toggleInterpolatorModes()
-        {
-            for (const CCallsign &cs : this->keys())
-            {
-                (*this)[cs].toggleInterpolatorMode();
-            }
-        }
-
-        void CSimConnectObjects::toggleInterpolatorMode(const CCallsign &callsign)
-        {
-            if (!this->contains(callsign)) { return; }
-            (*this)[callsign].toggleInterpolatorMode();
-        }
-
-        int CSimConnectObjects::setInterpolatorModes(CInterpolatorMulti::Mode mode)
-        {
-            int c = 0;
-            for (const CCallsign &cs : this->keys())
-            {
-                if ((*this)[cs].setInterpolatorMode(mode)) c++;
-            }
-            return c;
-        }
     } // namespace
 } // namespace
diff --git a/src/plugins/simulator/fsxcommon/simconnectobject.h b/src/plugins/simulator/fsxcommon/simconnectobject.h
index 3d57f0abd..0110a74f8 100644
--- a/src/plugins/simulator/fsxcommon/simconnectobject.h
+++ b/src/plugins/simulator/fsxcommon/simconnectobject.h
@@ -163,11 +163,8 @@ namespace BlackSimPlugin
             //! \copydoc BlackMisc::Simulation::CInterpolatorMulti::toggleMode
             void toggleInterpolatorMode();
 
-            //! \copydoc BlackMisc::Simulation::CInterpolatorMulti::setMode
-            bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode);
-
             //! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatorInfo
-            QString getInterpolatorInfo() const;
+            QString getInterpolatorInfo(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
 
             //! \copydoc BlackMisc::Simulation::CInterpolator::attachLogger
             void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger);
@@ -191,7 +188,7 @@ namespace BlackSimPlugin
                 BlackMisc::Simulation::CPartsStatus &partsStatus, bool log) const;
 
             //! Last interpolated situation
-            const BlackMisc::Aviation::CAircraftSituation &getLastInterpolatedSituation() const;
+            const BlackMisc::Aviation::CAircraftSituation &getLastInterpolatedSituation(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
 
             //! Interpolator
             BlackMisc::Simulation::CInterpolatorMulti *getInterpolator() const { return m_interpolator.data(); }
@@ -274,15 +271,6 @@ namespace BlackSimPlugin
 
             //! Contains object of type
             bool containsType(CSimConnectObject::SimObjectType type) const;
-
-            //! Toggle interpolator modes
-            void toggleInterpolatorModes();
-
-            //! Toggle interpolator modes
-            void toggleInterpolatorMode(const BlackMisc::Aviation::CCallsign &callsign);
-
-            //! Set interpolator modes
-            int setInterpolatorModes(BlackMisc::Simulation::CInterpolatorMulti::Mode mode);
         };
     } // namespace
 } // namespace
diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp
index eb87b6045..1d537365a 100644
--- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp
+++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp
@@ -242,21 +242,6 @@ namespace BlackSimPlugin
             return CCallsignSet(m_simConnectObjects.keys());
         }
 
-        bool CSimulatorFsxCommon::setInterpolatorMode(CInterpolatorMulti::Mode mode, const CCallsign &callsign)
-        {
-            if (mode == CInterpolatorMulti::ModeUnknown) { return false; }
-            if (callsign.isEmpty())
-            {
-                const int c = m_simConnectObjects.setInterpolatorModes(mode);
-                return c > 0;
-            }
-            else
-            {
-                if (!m_simConnectObjects.contains(callsign)) { return false; }
-                return m_simConnectObjects[callsign].setInterpolatorMode(mode);
-            }
-        }
-
         CStatusMessageList CSimulatorFsxCommon::debugVerifyStateAfterAllAircraftRemoved() const
         {
             CStatusMessageList msgs;
@@ -539,7 +524,8 @@ namespace BlackSimPlugin
 
             // CElevationPlane: deg, deg, feet
             // we only remember near ground
-            if (simObject.getLastInterpolatedSituation().canLikelySkipNearGroundInterpolation()) { return; }
+            const CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupPerCallsignOrDefault(simObject.getCallsign());
+            if (simObject.getLastInterpolatedSituation(setup.getInterpolatorMode()).canLikelySkipNearGroundInterpolation()) { return; }
 
             CElevationPlane elevation(remoteAircraftData.latitudeDeg, remoteAircraftData.longitudeDeg, remoteAircraftData.elevationFt);
             elevation.setSinglePointRadius();
@@ -763,10 +749,11 @@ namespace BlackSimPlugin
                 CStatusMessage msg;
                 if (!simObject.getAircraftModelString().isEmpty())
                 {
+                    const CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupPerCallsignOrDefault(callsign);
                     m_addPendingAircraft.replaceOrAddByCallsign(simObject.getAircraft());
                     msg = CLogMessage(this).warning("Aircraft removed, '%1' '%2' object id '%3' out of reality bubble or other reason. Interpolator: '%4'")
                           << callsign.toQString() << simObject.getAircraftModelString()
-                          << objectID << simObject.getInterpolatorInfo();
+                          << objectID << simObject.getInterpolatorInfo(setup.getInterpolatorMode());
                 }
                 else
                 {
diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h
index 1756cb9de..3b6fde72b 100644
--- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h
+++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h
@@ -127,7 +127,6 @@ namespace BlackSimPlugin
             virtual void displayTextMessage(const BlackMisc::Network::CTextMessage &message) const override;
             virtual bool isPhysicallyRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) const override;
             virtual BlackMisc::Aviation::CCallsignSet physicallyRenderedAircraft() const override;
-            virtual bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode, const BlackMisc::Aviation::CCallsign &callsign) override;
             virtual void clearAllRemoteAircraftData() override;
             virtual BlackMisc::CStatusMessageList debugVerifyStateAfterAllAircraftRemoved() const override;
             //! @}
diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp
index 6cbf440f1..6c9f4300d 100644
--- a/src/plugins/simulator/xplane/simulatorxplane.cpp
+++ b/src/plugins/simulator/xplane/simulatorxplane.cpp
@@ -369,23 +369,6 @@ namespace BlackSimPlugin
             return false;
         }
 
-        bool CSimulatorXPlane::setInterpolatorMode(CInterpolatorMulti::Mode mode, const CCallsign &callsign)
-        {
-            if (!isConnected()) { return false; }
-
-            if (mode == CInterpolatorMulti::ModeUnknown) { return false; }
-            if (callsign.isEmpty())
-            {
-                const int c = m_xplaneAircraftObjects.setInterpolatorModes(mode);
-                return c > 0;
-            }
-            else
-            {
-                if (!m_xplaneAircraftObjects.contains(callsign)) { return false; }
-                return m_xplaneAircraftObjects[callsign].setInterpolatorMode(mode);
-            }
-        }
-
         QDBusConnection CSimulatorXPlane::connectionFromString(const QString &str)
         {
             if (str == CDBusServer::sessionBusAddress()) { return QDBusConnection::sessionBus(); }
diff --git a/src/plugins/simulator/xplane/simulatorxplane.h b/src/plugins/simulator/xplane/simulatorxplane.h
index 46d3e8058..12d42b5d8 100644
--- a/src/plugins/simulator/xplane/simulatorxplane.h
+++ b/src/plugins/simulator/xplane/simulatorxplane.h
@@ -134,7 +134,6 @@ namespace BlackSimPlugin
             virtual BlackMisc::Aviation::CAirportList getAirportsInRange() const override;
             virtual bool setTimeSynchronization(bool enable, const BlackMisc::PhysicalQuantities::CTime &offset) override;
             virtual BlackMisc::PhysicalQuantities::CTime getTimeSynchronizationOffset() const override { return BlackMisc::PhysicalQuantities::CTime(0, BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()); }
-            virtual bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode, const BlackMisc::Aviation::CCallsign &callsign) override;
             virtual void unload() override;
             //! @}
 
diff --git a/src/plugins/simulator/xplane/xplanempaircraft.cpp b/src/plugins/simulator/xplane/xplanempaircraft.cpp
index ee06991dc..e1b9c9499 100644
--- a/src/plugins/simulator/xplane/xplanempaircraft.cpp
+++ b/src/plugins/simulator/xplane/xplanempaircraft.cpp
@@ -36,22 +36,10 @@ namespace BlackSimPlugin
             return m_situationAsSent == position;
         }
 
-        void CXPlaneMPAircraft::toggleInterpolatorMode()
+        QString CXPlaneMPAircraft::getInterpolatorInfo(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
         {
             Q_ASSERT(m_interpolator);
-            m_interpolator->toggleMode();
-        }
-
-        bool CXPlaneMPAircraft::setInterpolatorMode(CInterpolatorMulti::Mode mode)
-        {
-            Q_ASSERT(m_interpolator);
-            return m_interpolator->setMode(mode);
-        }
-
-        QString CXPlaneMPAircraft::getInterpolatorInfo() const
-        {
-            Q_ASSERT(m_interpolator);
-            return m_interpolator->getInterpolatorInfo();
+            return m_interpolator->getInterpolatorInfo(mode);
         }
 
         void CXPlaneMPAircraft::attachInterpolatorLogger(CInterpolationLogger *logger)
@@ -91,15 +79,5 @@ namespace BlackSimPlugin
         {
             return CCallsignSet(this->keys());
         }
-
-        int CXPlaneMPAircraftObjects::setInterpolatorModes(CInterpolatorMulti::Mode mode)
-        {
-            int c = 0;
-            for (const CCallsign &cs : this->keys())
-            {
-                if ((*this)[cs].setInterpolatorMode(mode)) c++;
-            }
-            return c;
-        }
     } // namespace
 } // namespace
diff --git a/src/plugins/simulator/xplane/xplanempaircraft.h b/src/plugins/simulator/xplane/xplanempaircraft.h
index 8fc958810..382cb1fdc 100644
--- a/src/plugins/simulator/xplane/xplanempaircraft.h
+++ b/src/plugins/simulator/xplane/xplanempaircraft.h
@@ -70,14 +70,8 @@ namespace BlackSimPlugin
             //! Engine count
             int getEngineCount() const { return m_aircraft.getEnginesCount(); }
 
-            //! \copydoc BlackMisc::Simulation::CInterpolatorMulti::toggleMode
-            void toggleInterpolatorMode();
-
-            //! \copydoc BlackMisc::Simulation::CInterpolatorMulti::setMode
-            bool setInterpolatorMode(BlackMisc::Simulation::CInterpolatorMulti::Mode mode);
-
             //! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatorInfo
-            QString getInterpolatorInfo() const;
+            QString getInterpolatorInfo(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
 
             //! \copydoc BlackMisc::Simulation::CInterpolator::attachLogger
             void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger);
@@ -128,9 +122,6 @@ namespace BlackSimPlugin
 
             //! Toggle interpolator modes
             void toggleInterpolatorMode(const BlackMisc::Aviation::CCallsign &callsign);
-
-            //! Set interpolator modes
-            int setInterpolatorModes(BlackMisc::Simulation::CInterpolatorMulti::Mode mode);
         };
     } // namespace
 } // namespace