public static UiHelper.IView View() { // Load Auto Open status. ReloadConfig(); var setAutoOpen = new UiHelper.DynamicToggleView("Auto Open", "Open this view when entering the Flight or Tracking Center scenes.", () => AutoOpenLander, () => true, v => AutoOpenLander = v); var bodySelector = new UiHelper.ListSelectView <CelestialBody>("Body", () => FlightGlobals.fetch == null ? null : FlightGlobals.fetch.bodies, null, Utils.CbToString); bodySelector.CurrentlySelected = FlightGlobals.fetch == null ? null : FlightGlobals.ActiveVessel == null ? Planetarium.fetch.Home : FlightGlobals.ActiveVessel.mainBody; var lat = new UiHelper.TextBoxView <double>("Lat", "Latitude (North/South). Between +90 (North) and -90 (South).", 0.001d, latTryParse); var lon = new UiHelper.TextBoxView <double>("Lon", "Longitude (East/West). Converts to less than 360 degrees.", 0.001d, myTryParse); var alt = new UiHelper.TextBoxView <double>("Alt", "Altitude (Up/Down). Distance above the surface.", 20, altTryParse); var setRot = new UiHelper.ToggleView("Force Rotation", "Rotates vessel such that up on the vessel is up when landing. Otherwise, the current orientation is kept relative to the body.", true); Func <bool> isValid = () => lat.Valid && lon.Valid && alt.Valid; Action <double, double, double, CelestialBody> load = (latVal, lonVal, altVal, body) => { lat.Object = latVal; lon.Object = lonVal; alt.Object = altVal; bodySelector.CurrentlySelected = body; }; // Load last entered values. DoLander.LoadLast(load); return(new UiHelper.VerticalView(new UiHelper.IView[] { setAutoOpen, bodySelector, new UiHelper.ConditionalView(() => FlightGlobals.fetch != null && FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.mainBody != bodySelector.CurrentlySelected, new UiHelper.LabelView("Landing on a different body is not recommended.", "This may destroy the vessel. Use the Orbit Editor to orbit the body first, then land on it.")), lat, new UiHelper.ConditionalView(() => !lat.Valid, new UiHelper.LabelView("Latitude must be a number from 0 to (+/-)89.9.", "Values too close to the poles ((+/-)90) can crash KSP, values beyond that are invalid for a latitude.")), lon, alt, new UiHelper.ConditionalView(() => alt.Object < 0, new UiHelper.LabelView("Altitude must be a positive number.", "This may destroy the vessel. Values less than 0 are sub-surface.")), setRot, new UiHelper.ConditionalView(() => !isValid(), new UiHelper.ButtonView("Cannot Land", "Entered location is invalid. Correct items in red.", null)), new UiHelper.ConditionalView(() => !DoLander.IsLanding() && isValid(), new UiHelper.ButtonView("Land", "Teleport to entered location, then slowly lower to surface.", () => DoLander.ToggleLanding(lat.Object, lon.Object, alt.Object, bodySelector.CurrentlySelected, setRot.Value, load))), new UiHelper.ConditionalView(() => DoLander.IsLanding(), new UiHelper.ButtonView("Drop (CAUTION!)", "Release vessel to gravity.", () => DoLander.ToggleLanding(lat.Object, lon.Object, alt.Object, bodySelector.CurrentlySelected, setRot.Value, load))), new UiHelper.ConditionalView(() => DoLander.IsLanding(), new UiHelper.LabelView("LANDING IN PROGRESS.", "Vessel is being lowered to the surface.")), //Launch button here new UiHelper.ConditionalView(() => DoLander.IsLanding(), new UiHelper.LabelView(changeHelpString(), "Change location slightly.")), new UiHelper.ConditionalView(() => !DoLander.IsLanding(), new UiHelper.ButtonView("Land Here", "Stop at current location, then slowly lower to surface.", () => DoLander.LandHere(load))), new UiHelper.ListSelectView <Vessel>("Set to vessel", DoLander.LandedVessels, select => DoLander.SetToLanded(load, select), Extensions.VesselToString), new UiHelper.ButtonView("Current", "Set to current location.", () => DoLander.SetToCurrent(load)), new UiHelper.ConditionalView(isValid, new UiHelper.ButtonView("Save", "Save the entered location.", () => DoLander.AddSavedCoords(lat.Object, lon.Object, alt.Object, bodySelector.CurrentlySelected))), new UiHelper.ButtonView("Load", "Load a saved location.", () => DoLander.Load(load)), new UiHelper.ButtonView("Delete", "Delete a saved location.", DoLander.Delete), })); }
// Also known as "closure hell" public static UiHelper.IView View() { UiHelper.ListSelectView <OrbitDriver> currentlyEditing = null; Action <OrbitDriver> onCurrentlyEditingChange = null; var setToCurrentOrbit = new UiHelper.ButtonView("Set to current orbit", "Sets all the fields of the editor to reflect the orbit of the currently selected vessel", () => onCurrentlyEditingChange(currentlyEditing.CurrentlySelected)); var referenceSelector = new UiHelper.ListSelectView <CelestialBody>("Reference body", () => FlightGlobals.fetch == null ? null : FlightGlobals.fetch.bodies, null, Utils.CbToString); #region Simple var simpleAltitude = new UiHelper.TextBoxView <double>("Altitude", "Altitude of circular orbit", 110000, SiSuffix.TryParse); var simpleApply = new UiHelper.ConditionalView(() => simpleAltitude.Valid && referenceSelector.CurrentlySelected != null, new UiHelper.ButtonView("Apply", "Sets the orbit", () => { OrbitEditor.Simple(currentlyEditing.CurrentlySelected, simpleAltitude.Object, referenceSelector.CurrentlySelected); currentlyEditing.ReInvokeOnSelect(); })); var simple = new UiHelper.VerticalView(new UiHelper.IView[] { simpleAltitude, referenceSelector, simpleApply, setToCurrentOrbit }); #endregion #region Complex var complexInclination = new UiHelper.TextBoxView <double>("Inclination", "How close to the equator the orbit plane is", 0, double.TryParse); var complexEccentricity = new UiHelper.TextBoxView <double>("Eccentricity", "How circular the orbit is (0=circular, 0.5=elliptical, 1=parabolic)", 0, double.TryParse); var complexSemiMajorAxis = new UiHelper.TextBoxView <double>("Semi-major axis", "Mean radius of the orbit (ish)", 10000000, SiSuffix.TryParse); var complexLongitudeAscendingNode = new UiHelper.TextBoxView <double>("Lon. of asc. node", "Longitude of the place where you cross the equator northwards", 0, double.TryParse); var complexArgumentOfPeriapsis = new UiHelper.TextBoxView <double>("Argument of periapsis", "Rotation of the orbit around the normal", 0, double.TryParse); var complexMeanAnomalyAtEpoch = new UiHelper.TextBoxView <double>("Mean anomaly at epoch", "Position along the orbit at the epoch", 0, double.TryParse); var complexEpoch = new UiHelper.TextBoxView <double>("Epoch", "Epoch at which mEp is measured", 0, SiSuffix.TryParse); var complexEpochNow = new UiHelper.ButtonView("Set epoch to now", "Sets the Epoch field to the current time", () => complexEpoch.Object = Planetarium.GetUniversalTime()); var complexApply = new UiHelper.ConditionalView(() => complexInclination.Valid && complexEccentricity.Valid && complexSemiMajorAxis.Valid && complexLongitudeAscendingNode.Valid && complexArgumentOfPeriapsis.Valid && complexMeanAnomalyAtEpoch.Valid && complexEpoch.Valid && referenceSelector.CurrentlySelected != null, new UiHelper.ButtonView("Apply", "Sets the orbit", () => { OrbitEditor.Complex(currentlyEditing.CurrentlySelected, complexInclination.Object, complexEccentricity.Object, complexSemiMajorAxis.Object, complexLongitudeAscendingNode.Object, complexArgumentOfPeriapsis.Object, complexMeanAnomalyAtEpoch.Object, complexEpoch.Object, referenceSelector.CurrentlySelected); currentlyEditing.ReInvokeOnSelect(); })); var complex = new UiHelper.VerticalView(new UiHelper.IView[] { complexInclination, complexEccentricity, complexSemiMajorAxis, complexLongitudeAscendingNode, complexArgumentOfPeriapsis, complexMeanAnomalyAtEpoch, complexEpoch, complexEpochNow, referenceSelector, complexApply, setToCurrentOrbit }); #endregion #region Graphical UiHelper.SliderView graphicalInclination = null; UiHelper.SliderView graphicalEccentricity = null; UiHelper.SliderView graphicalPeriapsis = null; UiHelper.SliderView graphicalLongitudeAscendingNode = null; UiHelper.SliderView graphicalArgumentOfPeriapsis = null; UiHelper.SliderView graphicalMeanAnomaly = null; double graphicalEpoch = 0; Action <double> graphicalOnChange = ignored => { OrbitEditor.Graphical(currentlyEditing.CurrentlySelected, graphicalInclination.Value, graphicalEccentricity.Value, graphicalPeriapsis.Value, graphicalLongitudeAscendingNode.Value, graphicalArgumentOfPeriapsis.Value, graphicalMeanAnomaly.Value, graphicalEpoch); currentlyEditing.ReInvokeOnSelect(); }; graphicalInclination = new UiHelper.SliderView("Inclination", "How close to the equator the orbit plane is", graphicalOnChange); graphicalEccentricity = new UiHelper.SliderView("Eccentricity", "How circular the orbit is", graphicalOnChange); graphicalPeriapsis = new UiHelper.SliderView("Periapsis", "Lowest point in the orbit", graphicalOnChange); graphicalLongitudeAscendingNode = new UiHelper.SliderView("Lon. of asc. node", "Longitude of the place where you cross the equator northwards", graphicalOnChange); graphicalArgumentOfPeriapsis = new UiHelper.SliderView("Argument of periapsis", "Rotation of the orbit around the normal", graphicalOnChange); graphicalMeanAnomaly = new UiHelper.SliderView("Mean anomaly", "Position along the orbit", graphicalOnChange); var graphical = new UiHelper.VerticalView(new UiHelper.IView[] { graphicalInclination, graphicalEccentricity, graphicalPeriapsis, graphicalLongitudeAscendingNode, graphicalArgumentOfPeriapsis, graphicalMeanAnomaly, setToCurrentOrbit }); #endregion #region Velocity var velocitySpeed = new UiHelper.TextBoxView <double>("Speed", "dV to apply", 0, SiSuffix.TryParse); var velocityDirection = new UiHelper.ListSelectView <OrbitEditor.VelocityChangeDirection>("Direction", () => OrbitEditor.AllVelocityChanges); var velocityApply = new UiHelper.ConditionalView(() => velocitySpeed.Valid, new UiHelper.ButtonView("Apply", "Adds the selected velocity to the orbit", () => { OrbitEditor.Velocity(currentlyEditing.CurrentlySelected, velocityDirection.CurrentlySelected, velocitySpeed.Object); })); var velocity = new UiHelper.VerticalView(new UiHelper.IView[] { velocitySpeed, velocityDirection, velocityApply }); #endregion #region Rendezvous var rendezvousLeadTime = new UiHelper.TextBoxView <double>("Lead time", "How many seconds off to rendezvous at (zero = on top of each other, bad)", 1, SiSuffix.TryParse); var rendezvousVessel = new UiHelper.ListSelectView <Vessel>("Target vessel", () => FlightGlobals.fetch == null ? null : FlightGlobals.fetch.vessels, null, Extensions.VesselToString); var rendezvousApply = new UiHelper.ConditionalView(() => rendezvousLeadTime.Valid && rendezvousVessel.CurrentlySelected != null, new UiHelper.ButtonView("Apply", "Rendezvous", () => { OrbitEditor.Rendezvous(currentlyEditing.CurrentlySelected, rendezvousLeadTime.Object, rendezvousVessel.CurrentlySelected); })); // rendezvous gets special ConditionalView to force only editing of planets var rendezvous = new UiHelper.ConditionalView(() => currentlyEditing.CurrentlySelected != null && currentlyEditing.CurrentlySelected.vessel != null, new UiHelper.VerticalView(new UiHelper.IView[] { rendezvousLeadTime, rendezvousVessel, rendezvousApply })); #endregion #region CurrentlyEditing onCurrentlyEditingChange = newEditing => { if (newEditing == null) { return; } { double altitude; CelestialBody body; OrbitEditor.GetSimple(newEditing, out altitude, out body); simpleAltitude.Object = altitude; referenceSelector.CurrentlySelected = body; } { double inclination; double eccentricity; double semiMajorAxis; double longitudeAscendingNode; double argumentOfPeriapsis; double meanAnomalyAtEpoch; double epoch; CelestialBody body; OrbitEditor.GetComplex(newEditing, out inclination, out eccentricity, out semiMajorAxis, out longitudeAscendingNode, out argumentOfPeriapsis, out meanAnomalyAtEpoch, out epoch, out body); complexInclination.Object = inclination; complexEccentricity.Object = eccentricity; complexSemiMajorAxis.Object = semiMajorAxis; complexLongitudeAscendingNode.Object = longitudeAscendingNode; complexArgumentOfPeriapsis.Object = argumentOfPeriapsis; complexMeanAnomalyAtEpoch.Object = meanAnomalyAtEpoch; complexEpoch.Object = epoch; referenceSelector.CurrentlySelected = body; } { double inclination; double eccentricity; double periapsis; double longitudeAscendingNode; double argumentOfPeriapsis; double meanAnomaly; OrbitEditor.GetGraphical(newEditing, out inclination, out eccentricity, out periapsis, out longitudeAscendingNode, out argumentOfPeriapsis, out meanAnomaly, out graphicalEpoch); graphicalInclination.Value = inclination; graphicalEccentricity.Value = eccentricity; graphicalPeriapsis.Value = periapsis; graphicalLongitudeAscendingNode.Value = longitudeAscendingNode; graphicalArgumentOfPeriapsis.Value = argumentOfPeriapsis; graphicalMeanAnomaly.Value = meanAnomaly; } { OrbitEditor.VelocityChangeDirection direction; double speed; OrbitEditor.GetVelocity(newEditing, out direction, out speed); velocityDirection.CurrentlySelected = direction; velocitySpeed.Object = speed; } }; currentlyEditing = new UiHelper.ListSelectView <OrbitDriver>("Currently editing", OrbitEditor.OrderedOrbits, onCurrentlyEditingChange, Extensions.OrbitDriverToString); if (FlightGlobals.fetch != null && FlightGlobals.fetch.activeVessel != null && FlightGlobals.fetch.activeVessel.orbitDriver != null) { currentlyEditing.CurrentlySelected = FlightGlobals.fetch.activeVessel.orbitDriver; } #endregion /* * var savePlanet = new UiHelper.ButtonView("Save planet", "Saves the current orbit of the planet to a file, so it stays edited even after a restart. Delete the file named the planet's name in " + ConfigHelper.GetPath(null) + " to undo.", * () => Planet.PlanetEditor.SavePlanet(currentlyEditing.CurrentlySelected.celestialBody)); * var resetPlanet = new UiHelper.ButtonView("Reset to defaults", "Reset the selected planet to defaults", * () => Planet.PlanetEditor.ResetToDefault(currentlyEditing.CurrentlySelected.celestialBody)); * * var planetButtons = new UiHelper.ConditionalView(() => currentlyEditing.CurrentlySelected?.celestialBody != null, * new UiHelper.VerticalView(new UiHelper.IView[] * { * savePlanet, * resetPlanet * })); */ var tabs = new UiHelper.TabView(new List <KeyValuePair <string, UiHelper.IView> >() { new KeyValuePair <string, UiHelper.IView>("Simple", simple), new KeyValuePair <string, UiHelper.IView>("Complex", complex), new KeyValuePair <string, UiHelper.IView>("Graphical", graphical), new KeyValuePair <string, UiHelper.IView>("Velocity", velocity), new KeyValuePair <string, UiHelper.IView>("Rendezvous", rendezvous), }); return(new UiHelper.VerticalView(new UiHelper.IView[] { currentlyEditing, //planetButtons, new UiHelper.ConditionalView(() => currentlyEditing.CurrentlySelected != null, tabs) })); }