public FlightPlanner(PrincipiaPluginAdapter adapter, PredictedVessel predicted_vessel) : base(adapter, predicted_vessel) { adapter_ = adapter; predicted_vessel_ = predicted_vessel; final_time_ = new DifferentialSlider( label: "Plan length", unit: null, log10_lower_rate: log10_time_lower_rate_, log10_upper_rate: log10_time_upper_rate_, min_value: 10, max_value: double.PositiveInfinity, formatter: FormatPlanLength, parser: TryParsePlanLength, field_width: 7); final_trajectory_analyser_ = new PlannedOrbitAnalyser(adapter, predicted_vessel); }
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; } } } }
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; } } } }