Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 60c82a7c7ad5
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 08814d6b415d
Choose a head ref
  • 7 commits
  • 1 file changed
  • 1 contributor

Commits on Apr 9, 2019

  1. Copy the full SHA
    2d2aadf View commit details
  2. Copy the full SHA
    79f1955 View commit details

Commits on Apr 10, 2019

  1. Avoid flickering.

    pleroy committed Apr 10, 2019
    Copy the full SHA
    515b0c4 View commit details
  2. Avoid repeated text areas.

    pleroy committed Apr 10, 2019
    Copy the full SHA
    f3fa1db View commit details
  3. Cleanup.

    pleroy committed Apr 10, 2019
    Copy the full SHA
    1162fb2 View commit details

Commits on Apr 11, 2019

  1. After egg's review.

    pleroy committed Apr 11, 2019
    Copy the full SHA
    7122098 View commit details
  2. Merge pull request #2131 from pleroy/Layout

    Fix null pointer exception in the flight plan and avoid UI flickering
    pleroy authored Apr 11, 2019
    Copy the full SHA
    08814d6 View commit details
Showing with 103 additions and 74 deletions.
  1. +103 −74 ksp_plugin_adapter/flight_planner.cs
177 changes: 103 additions & 74 deletions ksp_plugin_adapter/flight_planner.cs
Original file line number Diff line number Diff line change
@@ -115,6 +115,20 @@ private void UpdateVesselAndBurnEditors() {
}
}
}

if (burn_editors_ != null) {
string vessel_guid = vessel_?.id.ToString();
double current_time = plugin_.CurrentTime();
first_future_manoeuvre_ = null;
for (int i = 0; i < burn_editors_.Count; ++i) {
NavigationManoeuvre manoeuvre =
plugin_.FlightPlanGetManoeuvre(vessel_guid, i);
if (current_time < manoeuvre.final_time) {
first_future_manoeuvre_ = i;
break;
}
}
}
}

private void RenderFlightPlan(string vessel_guid) {
@@ -263,88 +277,104 @@ private void RenderUpcomingEvents() {
string vessel_guid = vessel_.id.ToString();
double current_time = plugin_.CurrentTime();
bool should_clear_guidance = true;
for (int i = 0; i < burn_editors_.Count; ++i) {

if (first_future_manoeuvre_.HasValue) {
int first_future_manoeuvre = first_future_manoeuvre_.Value;
NavigationManoeuvre manoeuvre =
plugin_.FlightPlanGetManoeuvre(vessel_guid, i);
// TODO(phl): Evil changes of widgets between layout and repaint...
if (manoeuvre.final_time > current_time) {
if (manoeuvre.burn.initial_time > current_time) {
UnityEngine.GUILayout.TextArea("Upcoming manœuvre: #" + (i + 1));
UnityEngine.GUILayout.Label(
"Ignition " + FormatTimeSpan(TimeSpan.FromSeconds(
current_time - manoeuvre.burn.initial_time)));
} else {
UnityEngine.GUILayout.TextArea("Ongoing manœuvre: #" + (i + 1));
UnityEngine.GUILayout.Label(
"Cutoff " + FormatTimeSpan(TimeSpan.FromSeconds(
current_time - manoeuvre.final_time)));
}
// In career mode, the patched conic solver may be null. In that case
// we do not offer the option of showing the manœuvre on the navball,
// even though the flight planner is still available to plan it.
// TODO(egg): We may want to consider setting the burn vector directly
// rather than going through the solver.
if (vessel_.patchedConicSolver != null) {
using (new UnityEngine.GUILayout.HorizontalScope()) {
show_guidance_ =
UnityEngine.GUILayout.Toggle(show_guidance_, "Show on navball");
if (UnityEngine.GUILayout.Button("Warp to manœuvre")) {
TimeWarp.fetch.WarpTo(manoeuvre.burn.initial_time - 60);
}
}
XYZ guidance = plugin_.FlightPlanGetGuidance(vessel_guid, i);
if (show_guidance_ &&
!double.IsNaN(guidance.x + guidance.y + guidance.z)) {
if (guidance_node_ == null ||
!vessel_.patchedConicSolver.maneuverNodes.Contains(
guidance_node_)) {
while (vessel_.patchedConicSolver.maneuverNodes.Count > 0) {
vessel_.patchedConicSolver.maneuverNodes.Last().RemoveSelf();
}
guidance_node_ = vessel_.patchedConicSolver.AddManeuverNode(
manoeuvre.burn.initial_time);
} else if (vessel_.patchedConicSolver.maneuverNodes.Count > 1) {
while (vessel_.patchedConicSolver.maneuverNodes.Count > 1) {
if (vessel_.patchedConicSolver.maneuverNodes.First() ==
guidance_node_) {
vessel_.patchedConicSolver.maneuverNodes.Last().RemoveSelf();
} else {
vessel_.patchedConicSolver.maneuverNodes.First().RemoveSelf();
}
}
}
var stock_orbit = guidance_node_.patch;
Vector3d stock_velocity_at_node_time =
stock_orbit.getOrbitalVelocityAtUT(
manoeuvre.burn.initial_time).xzy;
Vector3d stock_displacement_from_parent_at_node_time =
stock_orbit.getRelativePositionAtUT(
manoeuvre.burn.initial_time).xzy;
UnityEngine.Quaternion stock_frenet_frame_to_world =
UnityEngine.Quaternion.LookRotation(
stock_velocity_at_node_time,
Vector3d.Cross(
stock_velocity_at_node_time,
stock_displacement_from_parent_at_node_time));
guidance_node_.DeltaV =
((Vector3d)manoeuvre.burn.delta_v).magnitude *
(Vector3d)(UnityEngine.Quaternion.Inverse(
stock_frenet_frame_to_world) *
(Vector3d)guidance);
guidance_node_.UT = manoeuvre.burn.initial_time;
vessel_.patchedConicSolver.UpdateFlightPlan();
should_clear_guidance = false;
plugin_.FlightPlanGetManoeuvre(vessel_guid, first_future_manoeuvre);
if (manoeuvre.burn.initial_time > current_time) {
UnityEngine.GUILayout.TextArea("Upcoming manœuvre: #" +
(first_future_manoeuvre + 1));
UnityEngine.GUILayout.Label(
"Ignition " + FormatTimeSpan(TimeSpan.FromSeconds(
current_time - manoeuvre.burn.initial_time)));
} else {
UnityEngine.GUILayout.TextArea("Ongoing manœuvre: #" +
(first_future_manoeuvre + 1));
UnityEngine.GUILayout.Label(
"Cutoff " + FormatTimeSpan(TimeSpan.FromSeconds(
current_time - manoeuvre.final_time)));
}
// In career mode, the patched conic solver may be null. In that case
// we do not offer the option of showing the manœuvre on the navball,
// even though the flight planner is still available to plan it.
// TODO(egg): We may want to consider setting the burn vector directly
// rather than going through the solver.
if (vessel_.patchedConicSolver != null) {
using (new UnityEngine.GUILayout.HorizontalScope()) {
show_guidance_ =
UnityEngine.GUILayout.Toggle(show_guidance_, "Show on navball");
if (UnityEngine.GUILayout.Button("Warp to manœuvre")) {
TimeWarp.fetch.WarpTo(manoeuvre.burn.initial_time - 60);
}
break;
}
should_clear_guidance &= ShowGuidance(manoeuvre,
first_future_manoeuvre);
}
} else {
// Reserve some space to avoid the UI changing shape if we have
// nothing to say.
UnityEngine.GUILayout.TextArea("All manœuvres are in the past");
UnityEngine.GUILayout.Space(Width(1));
UnityEngine.GUILayout.Space(Width(1));
}

if (should_clear_guidance && guidance_node_ != null) {
guidance_node_.RemoveSelf();
guidance_node_ = null;
}
}

// Returns true iff the guidance node should be cleared.
internal bool ShowGuidance(NavigationManoeuvre manoeuvre,
int manoeuvre_index) {
string vessel_guid = vessel_.id.ToString();
XYZ guidance = plugin_.FlightPlanGetGuidance(vessel_guid, manoeuvre_index);
if (show_guidance_ &&
!double.IsNaN(guidance.x + guidance.y + guidance.z)) {
if (guidance_node_ == null ||
!vessel_.patchedConicSolver.maneuverNodes.Contains(
guidance_node_)) {
while (vessel_.patchedConicSolver.maneuverNodes.Count > 0) {
vessel_.patchedConicSolver.maneuverNodes.Last().RemoveSelf();
}
guidance_node_ = vessel_.patchedConicSolver.AddManeuverNode(
manoeuvre.burn.initial_time);
} else if (vessel_.patchedConicSolver.maneuverNodes.Count > 1) {
while (vessel_.patchedConicSolver.maneuverNodes.Count > 1) {
if (vessel_.patchedConicSolver.maneuverNodes.First() ==
guidance_node_) {
vessel_.patchedConicSolver.maneuverNodes.Last().RemoveSelf();
} else {
vessel_.patchedConicSolver.maneuverNodes.First().RemoveSelf();
}
}
}
var stock_orbit = guidance_node_.patch;
Vector3d stock_velocity_at_node_time =
stock_orbit.getOrbitalVelocityAtUT(
manoeuvre.burn.initial_time).xzy;
Vector3d stock_displacement_from_parent_at_node_time =
stock_orbit.getRelativePositionAtUT(
manoeuvre.burn.initial_time).xzy;
UnityEngine.Quaternion stock_frenet_frame_to_world =
UnityEngine.Quaternion.LookRotation(
stock_velocity_at_node_time,
Vector3d.Cross(
stock_velocity_at_node_time,
stock_displacement_from_parent_at_node_time));
guidance_node_.DeltaV =
((Vector3d)manoeuvre.burn.delta_v).magnitude *
(Vector3d)(UnityEngine.Quaternion.Inverse(
stock_frenet_frame_to_world) *
(Vector3d)guidance);
guidance_node_.UT = manoeuvre.burn.initial_time;
vessel_.patchedConicSolver.UpdateFlightPlan();
return false;
}
return true;
}

internal static string FormatPositiveTimeSpan (TimeSpan span) {
return (GameSettings.KERBIN_TIME
? (span.Days * 4 + span.Hours / 6).ToString("0000;0000") +
@@ -413,13 +443,12 @@ internal bool TryParsePlanLength(string str, out double value) {
return true;
}

// Not owned.
private readonly PrincipiaPluginAdapter adapter_;
private IntPtr plugin_ = IntPtr.Zero;
private IntPtr plugin_ = IntPtr.Zero; // Not owned.
private Vessel vessel_;
private List<BurnEditor> burn_editors_;

private DifferentialSlider final_time_;
private int? first_future_manoeuvre_;

private bool show_guidance_ = false;
private ManeuverNode guidance_node_;