private bool RenderCoast(int index, out double?orbital_period) { string vessel_guid = predicted_vessel.id.ToString(); var coast_analysis = plugin.FlightPlanGetCoastAnalysis( vessel_guid, revolutions_per_cycle: null, days_per_cycle: null, ground_track_revolution: 0, index); string orbit_description = null; orbital_period = coast_analysis.elements?.nodal_period; if (coast_analysis.primary_index.HasValue) { var primary = FlightGlobals.Bodies[coast_analysis.primary_index.Value]; int?nodal_revolutions = (int?)(coast_analysis.mission_duration / coast_analysis.elements?.nodal_period); orbit_description = OrbitAnalyser.OrbitDescription( primary, coast_analysis.elements, coast_analysis.recurrence, coast_analysis.ground_track, nodal_revolutions); } using (new UnityEngine.GUILayout.HorizontalScope()) { if (index == burn_editors_.Count) { final_trajectory_analyser_.index = index; final_trajectory_analyser_.RenderButton(); } else { double start_of_coast = index == 0 ? plugin.FlightPlanGetInitialTime( vessel_guid) : burn_editors_[index - 1].final_time; string coast_duration = (burn_editors_[index].initial_time - start_of_coast).FormatDuration( show_seconds: false); string coast_description = orbit_description == null ? L10N.CacheFormat( "#Principia_FlightPlan_Coast", coast_duration) : L10N.CacheFormat( "#Principia_FlightPlan_CoastInOrbit", orbit_description, coast_duration); UnityEngine.GUILayout.Label(coast_description); } if (UnityEngine.GUILayout.Button( L10N.CacheFormat("#Principia_FlightPlan_AddManœuvre"), GUILayoutWidth(4))) { double initial_time; if (index == 0) { initial_time = plugin.CurrentTime() + 60; } else { initial_time = plugin.FlightPlanGetManoeuvre(vessel_guid, index - 1).final_time + 60; } var editor = new BurnEditor(adapter_, predicted_vessel, initial_time, index, get_burn_at_index: burn_editors_. ElementAtOrDefault); editor.minimized = false; Burn candidate_burn = editor.Burn(); var status = plugin.FlightPlanInsert( vessel_guid, candidate_burn, index); // 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, index)); burn_editors_.Insert(index, editor); UpdateBurnEditorIndices(); UpdateStatus(status, index); Shrink(); return(true); } // TODO(phl): The error messaging here will be either confusing or // wrong. The messages should mention the new manœuvre without // numbering it, since the numbering has not changed (“the new manœuvre // would overlap with manœuvre #1 or manœuvre #2” or something along // these lines). UpdateStatus(status, index); } } return(false); }
private void RenderPlanner(int window_id) { var old_skin = UnityEngine.GUI.skin; UnityEngine.GUI.skin = null; UnityEngine.GUILayout.BeginVertical(); if (vessel_ == null || vessel_ != FlightGlobals.ActiveVessel || !plugin_.HasVessel(vessel_.id.ToString())) { Reset(); } if (vessel_ != null) { string vessel_guid = vessel_.id.ToString(); if (burn_editors_ == null) { if (plugin_.HasVessel(vessel_guid)) { if (plugin_.FlightPlanExists(vessel_guid)) { burn_editors_ = new List <BurnEditor>(); for (int i = 0; i < plugin_.FlightPlanNumberOfManoeuvres(vessel_guid); ++i) { // Dummy initial time, we call |Reset| immediately afterwards. final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); burn_editors_.Add( new BurnEditor(adapter_, plugin_, vessel_, initial_time: 0)); burn_editors_.Last().Reset( plugin_.FlightPlanGetManoeuvre(vessel_guid, i)); } } else { if (UnityEngine.GUILayout.Button("Create flight plan")) { plugin_.FlightPlanCreate(vessel_guid, plugin_.CurrentTime() + 1000, vessel_.GetTotalMass()); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); Shrink(); } } } } else { if (final_time_.Render(enabled: true)) { plugin_.FlightPlanSetFinalTime(vessel_guid, final_time_.value); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); } AdaptiveStepParameters parameters = plugin_.FlightPlanGetAdaptiveStepParameters(vessel_guid); UnityEngine.GUILayout.BeginHorizontal(); UnityEngine.GUILayout.Label("Maximal step count per segment", UnityEngine.GUILayout.Width(150)); if (parameters.max_steps <= 100) { UnityEngine.GUILayout.Button("min"); } else if (UnityEngine.GUILayout.Button("-")) { parameters.max_steps /= 10; plugin_.FlightPlanSetAdaptiveStepParameters(vessel_guid, parameters); } UnityEngine.GUILayout.TextArea(parameters.max_steps.ToString(), UnityEngine.GUILayout.Width(150)); if (parameters.max_steps >= Int64.MaxValue / 10) { UnityEngine.GUILayout.Button("max"); } else if (UnityEngine.GUILayout.Button("+")) { parameters.max_steps *= 10; plugin_.FlightPlanSetAdaptiveStepParameters(vessel_guid, parameters); } UnityEngine.GUILayout.EndHorizontal(); UnityEngine.GUILayout.BeginHorizontal(); UnityEngine.GUILayout.Label("Tolerance", UnityEngine.GUILayout.Width(150)); 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", UnityEngine.GUILayout.Width(150)); 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); } UnityEngine.GUILayout.EndHorizontal(); double Δv = (from burn_editor in burn_editors_ select burn_editor.Δv()).Sum(); UnityEngine.GUILayout.Label( "Total Δv : " + Δv.ToString("0.000") + " m/s"); if (burn_editors_.Count == 0 && UnityEngine.GUILayout.Button("Delete flight plan")) { plugin_.FlightPlanDelete(vessel_guid); Reset(); } else { if (burn_editors_.Count > 0) { RenderUpcomingEvents(); } for (int i = 0; i < burn_editors_.Count - 1; ++i) { UnityEngine.GUILayout.TextArea("Manœuvre #" + (i + 1) + ":"); burn_editors_[i].Render(enabled: false); } if (burn_editors_.Count > 0) { BurnEditor last_burn = burn_editors_.Last(); UnityEngine.GUILayout.TextArea("Editing manœuvre #" + (burn_editors_.Count) + ":"); if (last_burn.Render(enabled: true)) { 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_, plugin_, vessel_, initial_time); 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(); } } } } UnityEngine.GUILayout.EndVertical(); UnityEngine.GUI.DragWindow( position: new UnityEngine.Rect(x: 0f, y: 0f, width: 10000f, height: 10000f)); UnityEngine.GUI.skin = old_skin; }
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 RenderPlanner(int window_id) { var old_skin = UnityEngine.GUI.skin; UnityEngine.GUI.skin = null; UnityEngine.GUILayout.BeginVertical(); { string vessel_guid = vessel_?.id.ToString(); if (vessel_guid == null || vessel_ != FlightGlobals.ActiveVessel || !plugin_.HasVessel(vessel_guid) || !plugin_.FlightPlanExists(vessel_guid) || plugin_.FlightPlanNumberOfManoeuvres(vessel_guid) != burn_editors_?.Count) { Reset(); } } if (vessel_ != null) { string vessel_guid = vessel_.id.ToString(); if (burn_editors_ == null) { if (plugin_.HasVessel(vessel_guid)) { if (plugin_.FlightPlanExists(vessel_guid)) { burn_editors_ = new List<BurnEditor>(); for (int i = 0; i < plugin_.FlightPlanNumberOfManoeuvres(vessel_guid); ++i) { // Dummy initial time, we call |Reset| immediately afterwards. final_time_.value = plugin_.FlightPlanGetDesiredFinalTime(vessel_guid); burn_editors_.Add( new BurnEditor(adapter_, plugin_, vessel_, initial_time : 0)); burn_editors_.Last().Reset( plugin_.FlightPlanGetManoeuvre(vessel_guid, i)); } } else { if (UnityEngine.GUILayout.Button("Create flight plan")) { plugin_.FlightPlanCreate(vessel_guid, plugin_.CurrentTime() + 1000, vessel_.GetTotalMass()); final_time_.value = plugin_.FlightPlanGetDesiredFinalTime(vessel_guid); Shrink(); } } } } else { 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); UnityEngine.GUILayout.TextField( (final_time_.value == actual_final_time) ? "" : "Timed out after " + FormatPositiveTimeSpan(TimeSpan.FromSeconds( actual_final_time - plugin_.FlightPlanGetInitialTime(vessel_guid)))); AdaptiveStepParameters parameters = plugin_.FlightPlanGetAdaptiveStepParameters(vessel_guid); UnityEngine.GUILayout.BeginHorizontal(); UnityEngine.GUILayout.BeginHorizontal(); UnityEngine.GUILayout.Label("Max. steps per segment:", UnityEngine.GUILayout.Width(150)); 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(), UnityEngine.GUILayout.Width(75)); 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); } UnityEngine.GUILayout.EndHorizontal(); UnityEngine.GUILayout.BeginHorizontal(); UnityEngine.GUILayout.Label("Tolerance:", UnityEngine.GUILayout.Width(75)); 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", UnityEngine.GUILayout.Width(75)); 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); } UnityEngine.GUILayout.EndHorizontal(); UnityEngine.GUILayout.EndHorizontal(); double Δv = (from burn_editor in burn_editors_ select burn_editor.Δv()).Sum(); UnityEngine.GUILayout.Label( "Total Δv : " + Δv.ToString("0.000") + " m/s"); if (burn_editors_.Count == 0 && UnityEngine.GUILayout.Button("Delete flight plan")) { plugin_.FlightPlanDelete(vessel_guid); Reset(); } else { if (burn_editors_.Count > 0) { RenderUpcomingEvents(); } for (int i = 0; i < burn_editors_.Count - 1; ++i) { UnityEngine.GUILayout.TextArea("Manœuvre #" + (i + 1) + ":"); burn_editors_[i].Render(enabled : false); } if (burn_editors_.Count > 0) { BurnEditor last_burn = burn_editors_.Last(); UnityEngine.GUILayout.TextArea("Editing manœuvre #" + (burn_editors_.Count) + ":"); if (last_burn.Render(enabled : true)) { 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_, plugin_, vessel_, initial_time); 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(); } } } } UnityEngine.GUILayout.EndVertical(); UnityEngine.GUI.DragWindow( position : new UnityEngine.Rect(x : 0f, y : 0f, width : 10000f, height : 10000f)); UnityEngine.GUI.skin = old_skin; }
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(); } } } }
private void RenderPlanner(int window_id) { var old_skin = UnityEngine.GUI.skin; UnityEngine.GUI.skin = null; UnityEngine.GUILayout.BeginVertical(); if (vessel_ == null || vessel_ != FlightGlobals.ActiveVessel || !plugin_.HasVessel(vessel_.id.ToString())) { Reset(); } if (vessel_ != null) { string vessel_guid = vessel_.id.ToString(); if (burn_editors_ == null) { if (plugin_.HasVessel(vessel_guid)) { if (plugin_.FlightPlanExists(vessel_guid)) { burn_editors_ = new List<BurnEditor>(); for (int i = 0; i < plugin_.FlightPlanNumberOfManoeuvres(vessel_guid); ++i) { // Dummy initial time, we call |Reset| immediately afterwards. final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); burn_editors_.Add( new BurnEditor(adapter_, plugin_, vessel_, initial_time : 0)); burn_editors_.Last().Reset( plugin_.FlightPlanGetManoeuvre(vessel_guid, i)); } } else { if (UnityEngine.GUILayout.Button("Create flight plan")) { plugin_.FlightPlanCreate(vessel_guid, plugin_.CurrentTime() + 1000, vessel_.GetTotalMass()); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); Shrink(); } } } } else { if (final_time_.Render(enabled: true)) { plugin_.FlightPlanSetFinalTime(vessel_guid, final_time_.value); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); } if (UnityEngine.GUILayout.Button("Delete flight plan")) { plugin_.FlightPlanDelete(vessel_guid); Reset(); } else { if (burn_editors_.Count > 0) { RenderUpcomingEvents(); } for (int i = 0; i < burn_editors_.Count - 1; ++i) { UnityEngine.GUILayout.TextArea("Manœuvre #" + (i + 1) + ":"); burn_editors_[i].Render(enabled : false); } if (burn_editors_.Count > 0) { BurnEditor last_burn = burn_editors_.Last(); UnityEngine.GUILayout.TextArea("Editing manœuvre #" + (burn_editors_.Count) + ":"); if (last_burn.Render(enabled : true)) { 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_, plugin_, vessel_, initial_time); 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(); } } } } UnityEngine.GUILayout.EndVertical(); UnityEngine.GUI.DragWindow( position : new UnityEngine.Rect(left : 0f, top : 0f, width : 10000f, height : 10000f)); UnityEngine.GUI.skin = old_skin; }
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(); } } } }
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; } } } }
private void RenderPlanner(int window_id) { var old_skin = UnityEngine.GUI.skin; UnityEngine.GUI.skin = null; UnityEngine.GUILayout.BeginVertical(); if (vessel_ == null || vessel_ != FlightGlobals.ActiveVessel || !plugin_.HasVessel(vessel_.id.ToString())) { Reset(); } if (vessel_ != null) { string vessel_guid = vessel_.id.ToString(); if (burn_editors_ == null) { if (plugin_.HasVessel(vessel_guid)) { if (plugin_.FlightPlanExists(vessel_guid)) { burn_editors_ = new List <BurnEditor>(); for (int i = 0; i < plugin_.FlightPlanNumberOfManoeuvres(vessel_guid); ++i) { // Dummy initial time, we call |Reset| immediately afterwards. final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); burn_editors_.Add( new BurnEditor(adapter_, plugin_, vessel_, initial_time: 0)); burn_editors_.Last().Reset( plugin_.FlightPlanGetManoeuvre(vessel_guid, i)); } } else { if (UnityEngine.GUILayout.Button("Create flight plan")) { plugin_.FlightPlanCreate(vessel_guid, plugin_.CurrentTime() + 1000, vessel_.GetTotalMass()); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); Shrink(); } } } } else { if (final_time_.Render(enabled: true)) { plugin_.FlightPlanSetFinalTime(vessel_guid, final_time_.value); final_time_.value = plugin_.FlightPlanGetFinalTime(vessel_guid); } if (UnityEngine.GUILayout.Button("Delete flight plan")) { plugin_.FlightPlanDelete(vessel_guid); Reset(); } else { if (burn_editors_.Count > 0) { RenderUpcomingEvents(); } for (int i = 0; i < burn_editors_.Count - 1; ++i) { UnityEngine.GUILayout.TextArea("Manœuvre #" + (i + 1) + ":"); burn_editors_[i].Render(enabled: false); } if (burn_editors_.Count > 0) { BurnEditor last_burn = burn_editors_.Last(); UnityEngine.GUILayout.TextArea("Editing manœuvre #" + (burn_editors_.Count) + ":"); if (last_burn.Render(enabled: true)) { 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_, plugin_, vessel_, initial_time); 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(); } } } } UnityEngine.GUILayout.EndVertical(); UnityEngine.GUI.DragWindow( position: new UnityEngine.Rect(left: 0f, top: 0f, width: 10000f, height: 10000f)); UnityEngine.GUI.skin = old_skin; }
private bool RenderCoast(int index) { string vessel_guid = predicted_vessel.id.ToString(); using (new UnityEngine.GUILayout.HorizontalScope()) { double start_of_coast = index == 0 ? plugin.FlightPlanGetInitialTime(vessel_guid) : burn_editors_[index - 1].final_time; string coast_description = index == burn_editors_.Count ? "Final trajectory" : $@"Coast for { (burn_editors_[index].initial_time - start_of_coast).FormatDuration(show_seconds : false)}"; UnityEngine.GUILayout.Label(coast_description); if (UnityEngine.GUILayout.Button("Add manœuvre", GUILayoutWidth(4))) { double initial_time; if (index == 0) { initial_time = plugin.CurrentTime() + 60; } else { initial_time = plugin.FlightPlanGetManoeuvre(vessel_guid, index - 1).final_time + 60; } var editor = new BurnEditor( adapter_, predicted_vessel, initial_time, index, get_burn_at_index: burn_editors_.ElementAtOrDefault); editor.minimized = false; Burn candidate_burn = editor.Burn(); var status = plugin.FlightPlanInsert( vessel_guid, candidate_burn, index); // 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, index)); burn_editors_.Insert(index, editor); UpdateBurnEditorIndices(); UpdateStatus(status, index); Shrink(); return(true); } // TODO(phl): The error messaging here will be either confusing or // wrong. The messages should mention the new manœuvre without // numbering it, since the numbering has not changed (“the new manœuvre // would overlap with manœuvre #1 or manœuvre #2” or something along // these lines). UpdateStatus(status, index); } } return(false); }