コード例 #1
0
ファイル: flight_planner.cs プロジェクト: pleroy/Principia
 private void UpdateAdaptiveStepParameters(
     ref FlightPlanAdaptiveStepParameters parameters)
 {
     parameters.length_integration_tolerance =
         integration_tolerances_[length_integration_tolerance_index_];
     parameters.speed_integration_tolerance =
         integration_tolerances_[speed_integration_tolerance_index_];
     parameters.max_steps = max_steps_[max_steps_index_];
 }
コード例 #2
0
ファイル: flight_planner.cs プロジェクト: pleroy/Principia
            private void RenderFlightPlan(string vessel_guid)
            {
                using (new UnityEngine.GUILayout.VerticalScope()) {
                    if (final_time_.Render(enabled: true))
                    {
                        var status =
                            plugin.FlightPlanSetDesiredFinalTime(
                                vessel_guid,
                                final_time_.value);
                        UpdateStatus(status, null);
                    }
                    // Always refresh the final time from C++ as it may have changed because
                    // the last burn changed.
                    final_time_.value_if_different =
                        plugin.FlightPlanGetDesiredFinalTime(vessel_guid);

                    FlightPlanAdaptiveStepParameters parameters =
                        plugin.FlightPlanGetAdaptiveStepParameters(vessel_guid);
                    length_integration_tolerance_index_ = Math.Max(
                        0,
                        Array.FindIndex(integration_tolerances_,
                                        (double tolerance) => tolerance >=
                                        parameters.
                                        length_integration_tolerance));
                    speed_integration_tolerance_index_ = Math.Max(
                        0,
                        Array.FindIndex(integration_tolerances_,
                                        (double tolerance) => tolerance >=
                                        parameters.
                                        speed_integration_tolerance));
                    max_steps_index_ = Math.Max(0,
                                                Array.FindIndex(
                                                    max_steps_,
                                                    (long step) =>
                                                    step >= parameters.max_steps));

                    using (new UnityEngine.GUILayout.HorizontalScope()) {
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label(
                                L10N.CacheFormat("#Principia_FlightPlan_MaxSteps"),
                                GUILayoutWidth(6));
                            if (max_steps_index_ == 0)
                            {
                                UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_DiscreteSelector_Min"));
                            }
                            else if (UnityEngine.GUILayout.Button("−"))
                            {
                                --max_steps_index_;
                                UpdateAdaptiveStepParameters(ref parameters);
                                var status =
                                    plugin.FlightPlanSetAdaptiveStepParameters(
                                        vessel_guid,
                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(
                                max_steps_[max_steps_index_].ToString(),
                                GUILayoutWidth(3));
                            if (max_steps_index_ == max_steps_.Length - 1)
                            {
                                UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_DiscreteSelector_Max"));
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                ++max_steps_index_;
                                UpdateAdaptiveStepParameters(ref parameters);
                                var status =
                                    plugin.FlightPlanSetAdaptiveStepParameters(
                                        vessel_guid,
                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label(
                                L10N.CacheFormat("#Principia_PredictionSettings_ToleranceLabel"),
                                GUILayoutWidth(3));
                            // Prior to Ἵππαρχος the tolerances were powers of 2, see #3395.
                            if (length_integration_tolerance_index_ == 0 ||
                                speed_integration_tolerance_index_ == 0)
                            {
                                UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_DiscreteSelector_Min"));
                            }
                            else if (UnityEngine.GUILayout.Button("−"))
                            {
                                --length_integration_tolerance_index_;
                                --speed_integration_tolerance_index_;
                                UpdateAdaptiveStepParameters(ref parameters);
                                var status =
                                    plugin.FlightPlanSetAdaptiveStepParameters(
                                        vessel_guid,
                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(
                                length_integration_tolerances_names_[
                                    length_integration_tolerance_index_],
                                GUILayoutWidth(3));
                            if (length_integration_tolerance_index_ ==
                                integration_tolerances_.Length - 1 ||
                                speed_integration_tolerance_index_ ==
                                integration_tolerances_.Length - 1)
                            {
                                UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_DiscreteSelector_Max"));
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                ++length_integration_tolerance_index_;
                                ++speed_integration_tolerance_index_;
                                UpdateAdaptiveStepParameters(ref parameters);
                                var status =
                                    plugin.FlightPlanSetAdaptiveStepParameters(
                                        vessel_guid,
                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                    }

                    double Δv = (from burn_editor in burn_editors_
                                 select burn_editor.Δv()).Sum();
                    UnityEngine.GUILayout.Label(L10N.CacheFormat(
                                                    "#Principia_FlightPlan_TotalΔv",
                                                    Δv.ToString("0.000")));

                    {
                        var    style   = Style.Warning(Style.Multiline(UnityEngine.GUI.skin.label));
                        string message = GetStatusMessage();
                        // Size the label explicitly so that it doesn't decrease when the
                        // message goes away: that causes annoying flicker.  The enclosing
                        // window has a width of 20 units, but not all of that is available,
                        // hence 19.
                        warning_height_ = Math.Max(warning_height_,
                                                   style.CalcHeight(
                                                       new UnityEngine.GUIContent(message),
                                                       Width(19)));
                        UnityEngine.GUILayout.Label(message,
                                                    style,
                                                    UnityEngine.GUILayout.Height(
                                                        warning_height_));
                    }

                    if (burn_editors_.Count == 0 &&
                        UnityEngine.GUILayout.Button(
                            L10N.CacheFormat("#Principia_FlightPlan_Delete")))
                    {
                        final_trajectory_analyser_.DisposeWindow();
                        final_trajectory_analyser_ =
                            new PlannedOrbitAnalyser(adapter_, predicted_vessel_);
                        plugin.FlightPlanDelete(vessel_guid);
                        ResetStatus();
                        Shrink();
                        // The state change will happen the next time we go through OnGUI.
                    }
                    else
                    {
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            if (UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_FlightPlan_Rebase")))
                            {
                                var status = plugin.FlightPlanRebase(
                                    vessel_guid,
                                    predicted_vessel.GetTotalMass());
                                UpdateStatus(status, null);
                                if (status.ok())
                                {
                                    // The final time does not change, but since it is displayed with
                                    // respect to the beginning of the flight plan, the text must be
                                    // recomputed.
                                    final_time_.ResetValue(
                                        plugin.FlightPlanGetDesiredFinalTime(vessel_guid));
                                    return;
                                }
                            }
                            if (plugin.FlightPlanCount(vessel_guid) < max_flight_plans &&
                                UnityEngine.GUILayout.Button(
                                    L10N.CacheFormat("#Principia_FlightPlan_Duplicate")))
                            {
                                plugin.FlightPlanDuplicate(vessel_guid);
                            }
                        }

                        if (burn_editors_.Count > 0)
                        {
                            RenderUpcomingEvents();
                        }

                        // Compute the final times for each manœuvre before displaying them.
                        var final_times = new List <double>();
                        for (int i = 0; i < burn_editors_.Count - 1; ++i)
                        {
                            final_times.Add(plugin.FlightPlanGetManoeuvre(vessel_guid, i + 1).
                                            burn.initial_time);
                        }
                        // Allow extending the flight plan.
                        final_times.Add(double.PositiveInfinity);

                        for (int i = 0; i < burn_editors_.Count; ++i)
                        {
                            Style.HorizontalLine();
                            if (RenderCoast(i, out double?orbital_period))
                            {
                                return;
                            }
                            Style.HorizontalLine();
                            BurnEditor burn = burn_editors_[i];
                            switch (burn.Render(
                                        header          :
                                        L10N.CacheFormat("#Principia_FlightPlan_ManœuvreHeader", i + 1),
                                        anomalous       : i >=
                                        burn_editors_.Count -
                                        number_of_anomalous_manœuvres_,
                                        burn_final_time : final_times[i],
                                        orbital_period  : orbital_period))
                            {
                            case BurnEditor.Event.Deleted: {
                                var status = plugin.FlightPlanRemove(vessel_guid, i);
                                UpdateStatus(status, null);
                                burn_editors_[i].Close();
                                burn_editors_.RemoveAt(i);
                                UpdateBurnEditorIndices();
                                Shrink();
                                return;
                            }

                            case BurnEditor.Event.Minimized:
                            case BurnEditor.Event.Maximized: {
                                Shrink();
                                return;
                            }

                            case BurnEditor.Event.Changed: {
                                var status =
                                    plugin.FlightPlanReplace(vessel_guid, burn.Burn(), i);
                                UpdateStatus(status, i);
                                burn.Reset(plugin.FlightPlanGetManoeuvre(vessel_guid, i));
                                break;
                            }

                            case BurnEditor.Event.None: {
                                break;
                            }
                            }
                        }
                        Style.HorizontalLine();
                        if (RenderCoast(burn_editors_.Count, orbital_period: out _))
                        {
                            return;
                        }
                    }
                }
            }
コード例 #3
0
            private void RenderFlightPlan(string vessel_guid)
            {
                using (new UnityEngine.GUILayout.VerticalScope()) {
                    if (final_time_.Render(enabled: true))
                    {
                        plugin.FlightPlanSetDesiredFinalTime(vessel_guid,
                                                             final_time_.value);
                        final_time_.value =
                            plugin.FlightPlanGetDesiredFinalTime(vessel_guid);
                    }
                    double actual_final_time =
                        plugin.FlightPlanGetActualFinalTime(vessel_guid);

                    FlightPlanAdaptiveStepParameters parameters =
                        plugin.FlightPlanGetAdaptiveStepParameters(vessel_guid);

                    using (new UnityEngine.GUILayout.HorizontalScope()) {
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Max. steps per segment:",
                                                        GUILayoutWidth(6));
                            const int factor = 4;
                            if (parameters.max_steps <= 100)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.max_steps /= factor;
                                plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                           parameters);
                            }
                            UnityEngine.GUILayout.TextArea(parameters.max_steps.ToString(),
                                                           GUILayoutWidth(3));
                            if (parameters.max_steps >= Int64.MaxValue / factor)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.max_steps *= factor;
                                plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                           parameters);
                            }
                        }
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Tolerance:",
                                                        GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance <= 1e-6)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.length_integration_tolerance /= 2;
                                parameters.speed_integration_tolerance  /= 2;
                                plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                           parameters);
                            }
                            UnityEngine.GUILayout.TextArea(
                                parameters.length_integration_tolerance.ToString("0.0e0") + " m",
                                GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance >= 1e6)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.length_integration_tolerance *= 2;
                                parameters.speed_integration_tolerance  *= 2;
                                plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                           parameters);
                            }
                        }
                    }

                    double Δv = (from burn_editor in burn_editors_
                                 select burn_editor.Δv()).Sum();
                    UnityEngine.GUILayout.Label(
                        "Total Δv : " + Δv.ToString("0.000") + " m/s");

                    string message = "";
                    if (final_time_.value != actual_final_time)
                    {
                        message = "Timed out after " +
                                  FormatPositiveTimeSpan(TimeSpan.FromSeconds(
                                                             actual_final_time -
                                                             plugin.FlightPlanGetInitialTime(vessel_guid)));
                    }
                    UnityEngine.GUILayout.Label(
                        message, Style.Warning(UnityEngine.GUI.skin.label));

                    if (burn_editors_.Count == 0 &&
                        UnityEngine.GUILayout.Button("Delete flight plan"))
                    {
                        plugin.FlightPlanDelete(vessel_guid);
                        Shrink();
                        // The state change will happen the next time we go through OnGUI.
                    }
                    else
                    {
                        if (burn_editors_.Count > 0)
                        {
                            RenderUpcomingEvents();
                        }
                        for (int i = 0; i < burn_editors_.Count - 1; ++i)
                        {
                            Style.HorizontalLine();
                            burn_editors_[i].Render(header: "Manœuvre #" + (i + 1),
                                                    enabled: false);
                        }
                        if (burn_editors_.Count > 0)
                        {
                            Style.HorizontalLine();
                            BurnEditor last_burn = burn_editors_.Last();
                            if (last_burn.Render(header: "Editing manœuvre #" +
                                                 (burn_editors_.Count),
                                                 enabled: true,
                                                 actual_final_time: actual_final_time))
                            {
                                plugin.FlightPlanReplaceLast(vessel_guid, last_burn.Burn());
                                last_burn.Reset(
                                    plugin.FlightPlanGetManoeuvre(vessel_guid,
                                                                  burn_editors_.Count - 1));
                            }
                            if (UnityEngine.GUILayout.Button(
                                    "Delete last manœuvre",
                                    UnityEngine.GUILayout.ExpandWidth(true)))
                            {
                                plugin.FlightPlanRemoveLast(vessel_guid);
                                burn_editors_.Last().Close();
                                burn_editors_.RemoveAt(burn_editors_.Count - 1);
                                Shrink();
                            }
                        }
                        if (UnityEngine.GUILayout.Button(
                                "Add manœuvre",
                                UnityEngine.GUILayout.ExpandWidth(true)))
                        {
                            double initial_time;
                            if (burn_editors_.Count == 0)
                            {
                                initial_time = plugin.CurrentTime() + 60;
                            }
                            else
                            {
                                initial_time = plugin.FlightPlanGetManoeuvre(
                                    vessel_guid,
                                    burn_editors_.Count - 1).final_time + 60;
                            }
                            var editor =
                                new BurnEditor(adapter_,
                                               vessel_,
                                               initial_time,
                                               index: burn_editors_.Count,
                                               previous_burn: burn_editors_.LastOrDefault());
                            Burn candidate_burn = editor.Burn();
                            bool inserted       = plugin.FlightPlanAppend(vessel_guid,
                                                                          candidate_burn);
                            if (inserted)
                            {
                                editor.Reset(plugin.FlightPlanGetManoeuvre(
                                                 vessel_guid, burn_editors_.Count));
                                burn_editors_.Add(editor);
                            }
                            Shrink();
                        }
                    }
                }
            }
コード例 #4
0
            private void RenderFlightPlan(string vessel_guid)
            {
                using (new UnityEngine.GUILayout.VerticalScope()) {
                    if (final_time_.Render(enabled: true))
                    {
                        var status = plugin.FlightPlanSetDesiredFinalTime(vessel_guid,
                                                                          final_time_.value);
                        UpdateStatus(status, null);
                        final_time_.value =
                            plugin.FlightPlanGetDesiredFinalTime(vessel_guid);
                    }

                    FlightPlanAdaptiveStepParameters parameters =
                        plugin.FlightPlanGetAdaptiveStepParameters(vessel_guid);

                    using (new UnityEngine.GUILayout.HorizontalScope()) {
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Max. steps per segment:",
                                                        GUILayoutWidth(6));
                            const int factor = 4;
                            if (parameters.max_steps <= 100)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.max_steps /= factor;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(parameters.max_steps.ToString(),
                                                           GUILayoutWidth(3));
                            if (parameters.max_steps >= long.MaxValue / factor)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.max_steps *= factor;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Tolerance:",
                                                        GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance <= 1e-6)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.length_integration_tolerance /= 2;
                                parameters.speed_integration_tolerance  /= 2;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(
                                parameters.length_integration_tolerance.ToString("0.0e0") + " m",
                                GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance >= 1e6)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.length_integration_tolerance *= 2;
                                parameters.speed_integration_tolerance  *= 2;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                    }

                    double Δv = (from burn_editor in burn_editors_
                                 select burn_editor.Δv()).Sum();
                    UnityEngine.GUILayout.Label(
                        "Total Δv : " + Δv.ToString("0.000") + " m/s");

                    {
                        var    style   = Style.Warning(Style.Multiline(UnityEngine.GUI.skin.label));
                        string message = GetStatusMessage();
                        // Size the label explicitly so that it doesn't decrease when the
                        // message goes away: that causes annoying flicker.  The enclosing
                        // window has a width of 20 units, but not all of that is available,
                        // hence 19.
                        warning_height_ = Math.Max(
                            warning_height_,
                            style.CalcHeight(new UnityEngine.GUIContent(message), Width(19)));
                        UnityEngine.GUILayout.Label(
                            message, style, UnityEngine.GUILayout.Height(warning_height_));
                    }

                    if (burn_editors_.Count == 0 &&
                        UnityEngine.GUILayout.Button("Delete flight plan"))
                    {
                        plugin.FlightPlanDelete(vessel_guid);
                        ResetStatus();
                        Shrink();
                        // The state change will happen the next time we go through OnGUI.
                    }
                    else
                    {
                        if (burn_editors_.Count > 0)
                        {
                            RenderUpcomingEvents();
                        }

                        // Compute the final times for each manœuvre before displaying them.
                        var final_times = new List <double>();
                        for (int i = 0; i < burn_editors_.Count - 1; ++i)
                        {
                            final_times.Add(
                                plugin.FlightPlanGetManoeuvre(vessel_guid, i + 1).
                                burn.initial_time);
                        }
                        final_times.Add(plugin.FlightPlanGetActualFinalTime(vessel_guid));
                        int number_of_anomalous_manœuvres =
                            plugin.FlightPlanNumberOfAnomalousManoeuvres(vessel_guid);

                        for (int i = 0; i < burn_editors_.Count; ++i)
                        {
                            Style.HorizontalLine();
                            BurnEditor burn = burn_editors_[i];
                            if (burn.Render(header          : "Manœuvre #" + (i + 1),
                                            anomalous       :
                                            i >= (burn_editors_.Count -
                                                  number_of_anomalous_manœuvres),
                                            burn_final_time : final_times[i]))
                            {
                                var status = plugin.FlightPlanReplace(vessel_guid, burn.Burn(), i);
                                UpdateStatus(status, i);
                                burn.Reset(plugin.FlightPlanGetManoeuvre(vessel_guid, i));
                            }
                        }

                        if (burn_editors_.Count > 0)
                        {
                            if (UnityEngine.GUILayout.Button(
                                    "Delete last manœuvre",
                                    UnityEngine.GUILayout.ExpandWidth(true)))
                            {
                                var status = plugin.FlightPlanRemoveLast(vessel_guid);
                                UpdateStatus(status, null);
                                burn_editors_.Last().Close();
                                burn_editors_.RemoveAt(burn_editors_.Count - 1);
                                Shrink();
                            }
                        }
                        if (UnityEngine.GUILayout.Button(
                                "Add manœuvre",
                                UnityEngine.GUILayout.ExpandWidth(true)))
                        {
                            double initial_time;
                            if (burn_editors_.Count == 0)
                            {
                                initial_time = plugin.CurrentTime() + 60;
                            }
                            else
                            {
                                initial_time = plugin.FlightPlanGetManoeuvre(
                                    vessel_guid,
                                    burn_editors_.Count - 1).final_time + 60;
                            }
                            var editor =
                                new BurnEditor(adapter_,
                                               vessel_,
                                               initial_time,
                                               index: burn_editors_.Count,
                                               previous_burn: burn_editors_.LastOrDefault());
                            Burn candidate_burn = editor.Burn();
                            var  status         = plugin.FlightPlanAppend(vessel_guid, candidate_burn);

                            // The previous call did not necessarily create a manœuvre.  Check if
                            // we need to add an editor.
                            int number_of_manœuvres =
                                plugin.FlightPlanNumberOfManoeuvres(vessel_guid);
                            if (number_of_manœuvres > burn_editors_.Count)
                            {
                                editor.Reset(plugin.FlightPlanGetManoeuvre(
                                                 vessel_guid, number_of_manœuvres - 1));
                                burn_editors_.Add(editor);
                                UpdateStatus(status, number_of_manœuvres - 1);
                            }
                            else
                            {
                                UpdateStatus(status, number_of_manœuvres);
                            }

                            Shrink();
                        }
                    }
                }
            }
コード例 #5
0
            private void RenderFlightPlan(string vessel_guid)
            {
                using (new UnityEngine.GUILayout.VerticalScope()) {
                    if (final_time_.Render(enabled: true))
                    {
                        var status = plugin.FlightPlanSetDesiredFinalTime(vessel_guid,
                                                                          final_time_.value);
                        UpdateStatus(status, null);
                    }
                    // Always refresh the final time from C++ as it may have changed because
                    // the last burn changed.
                    final_time_.value =
                        plugin.FlightPlanGetDesiredFinalTime(vessel_guid);

                    FlightPlanAdaptiveStepParameters parameters =
                        plugin.FlightPlanGetAdaptiveStepParameters(vessel_guid);

                    using (new UnityEngine.GUILayout.HorizontalScope()) {
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Max. steps per segment:",
                                                        GUILayoutWidth(6));
                            const int factor = 4;
                            if (parameters.max_steps <= 100)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.max_steps /= factor;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(parameters.max_steps.ToString(),
                                                           GUILayoutWidth(3));
                            if (parameters.max_steps >= long.MaxValue / factor)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.max_steps *= factor;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                        using (new UnityEngine.GUILayout.HorizontalScope()) {
                            UnityEngine.GUILayout.Label("Tolerance:",
                                                        GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance <= 1e-6)
                            {
                                UnityEngine.GUILayout.Button("min");
                            }
                            else if (UnityEngine.GUILayout.Button("-"))
                            {
                                parameters.length_integration_tolerance /= 2;
                                parameters.speed_integration_tolerance  /= 2;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                            UnityEngine.GUILayout.TextArea(
                                parameters.length_integration_tolerance.ToString("0.0e0") + " m",
                                GUILayoutWidth(3));
                            if (parameters.length_integration_tolerance >= 1e6)
                            {
                                UnityEngine.GUILayout.Button("max");
                            }
                            else if (UnityEngine.GUILayout.Button("+"))
                            {
                                parameters.length_integration_tolerance *= 2;
                                parameters.speed_integration_tolerance  *= 2;
                                var status = plugin.FlightPlanSetAdaptiveStepParameters(vessel_guid,
                                                                                        parameters);
                                UpdateStatus(status, null);
                            }
                        }
                    }

                    double Δv = (from burn_editor in burn_editors_
                                 select burn_editor.Δv()).Sum();
                    UnityEngine.GUILayout.Label(
                        "Total Δv : " + Δv.ToString("0.000") + " m/s");

                    {
                        var    style   = Style.Warning(Style.Multiline(UnityEngine.GUI.skin.label));
                        string message = GetStatusMessage();
                        // Size the label explicitly so that it doesn't decrease when the
                        // message goes away: that causes annoying flicker.  The enclosing
                        // window has a width of 20 units, but not all of that is available,
                        // hence 19.
                        warning_height_ = Math.Max(
                            warning_height_,
                            style.CalcHeight(new UnityEngine.GUIContent(message), Width(19)));
                        UnityEngine.GUILayout.Label(
                            message, style, UnityEngine.GUILayout.Height(warning_height_));
                    }

                    if (burn_editors_.Count == 0 &&
                        UnityEngine.GUILayout.Button("Delete flight plan"))
                    {
                        final_trajectory_analyser_.DisposeWindow();
                        final_trajectory_analyser_ = new PlannedOrbitAnalyser(adapter_,
                                                                              predicted_vessel_);
                        plugin.FlightPlanDelete(vessel_guid);
                        ResetStatus();
                        Shrink();
                        // The state change will happen the next time we go through OnGUI.
                    }
                    else
                    {
                        if (UnityEngine.GUILayout.Button("Rebase"))
                        {
                            var status = plugin.FlightPlanRebase(
                                vessel_guid, predicted_vessel.GetTotalMass());
                            UpdateStatus(status, null);
                            if (status.ok())
                            {
                                // The final time does not change, but since it is displayed with
                                // respect to the beginning of the flight plan, the text must be
                                // recomputed.
                                final_time_.ResetValue(
                                    plugin.FlightPlanGetDesiredFinalTime(vessel_guid));
                                return;
                            }
                        }

                        if (burn_editors_.Count > 0)
                        {
                            RenderUpcomingEvents();
                        }

                        // Compute the final times for each manœuvre before displaying them.
                        var final_times = new List <double>();
                        for (int i = 0; i < burn_editors_.Count - 1; ++i)
                        {
                            final_times.Add(
                                plugin.FlightPlanGetManoeuvre(vessel_guid, i + 1).
                                burn.initial_time);
                        }
                        // Allow extending the flight plan.
                        final_times.Add(double.PositiveInfinity);

                        for (int i = 0; i < burn_editors_.Count; ++i)
                        {
                            Style.HorizontalLine();
                            if (RenderCoast(i))
                            {
                                return;
                            }
                            Style.HorizontalLine();
                            BurnEditor burn = burn_editors_[i];
                            switch (burn.Render(header          : "Manœuvre #" + (i + 1),
                                                anomalous       :
                                                i >= (burn_editors_.Count -
                                                      number_of_anomalous_manœuvres_),
                                                burn_final_time : final_times[i]))
                            {
                            case BurnEditor.Event.Deleted: {
                                var status = plugin.FlightPlanRemove(vessel_guid, i);
                                UpdateStatus(status, null);
                                burn_editors_[i].Close();
                                burn_editors_.RemoveAt(i);
                                UpdateBurnEditorIndices();
                                Shrink();
                                return;
                            }

                            case BurnEditor.Event.Minimized:
                            case BurnEditor.Event.Maximized: {
                                Shrink();
                                return;
                            }

                            case BurnEditor.Event.Changed: {
                                var status =
                                    plugin.FlightPlanReplace(vessel_guid, burn.Burn(), i);
                                UpdateStatus(status, i);
                                burn.Reset(plugin.FlightPlanGetManoeuvre(vessel_guid, i));
                                break;
                            }

                            case BurnEditor.Event.None: {
                                break;
                            }
                            }
                        }
                        Style.HorizontalLine();
                        if (RenderCoast(burn_editors_.Count))
                        {
                            return;
                        }
                    }
                }
            }