/// <summary> /// Sort the transfers from a model. /// </summary> /// <returns>List of sorted transfers</returns> /// <param name="m">Model from which to sort transfers</param> /// <param name="how">Sort method</param> /// <param name="descend">True for descending sort, false for ascending</param> public static List <TransferModel> SortTransfers(AstrogationModel m, SortEnum how, bool descend) { List <TransferModel> transfers = new List <TransferModel>(m.transfers); switch (how) { case SortEnum.Name: transfers.Sort((a, b) => a?.destination?.GetName().CompareTo(b?.destination?.GetName()) ?? 0); break; case SortEnum.Position: // Use the natural/default ordering in the model break; case SortEnum.Time: transfers.Sort((a, b) => a?.ejectionBurn?.atTime?.CompareTo(b?.ejectionBurn?.atTime ?? 0) ?? 0); break; case SortEnum.DeltaV: transfers.Sort((a, b) => a?.ejectionBurn?.totalDeltaV.CompareTo(b?.ejectionBurn?.totalDeltaV) ?? 0); break; default: DbgFmt("Bad sort argument: {0}", how.ToString()); break; } if (descend) { transfers.Reverse(); } return(transfers); }
/// <summary> /// Construct a view for the given model. /// </summary> /// <param name="m">Model object for which to make a view</param> /// <param name="reset">Function to call when the view needs to be re-initiated</param> /// <param name="close">Function to call when the user clicks a close button</param> public AstrogationView(AstrogationModel m, ResetCallback reset, UnityAction close) : base( FlightGlobals.ActiveVessel != null ? mainWindowMinWidthWithVessel : mainWindowMinWidthWithoutVessel, mainWindowMinHeight, mainWindowSpacing, mainWindowPadding, TextAnchor.UpperCenter ) { model = m; resetCallback = reset; closeCallback = close; int width = FlightGlobals.ActiveVessel != null ? RowWidthWithVessel : RowWidthWithoutVessel; if (Settings.Instance.ShowSettings) { AddChild(new SettingsView(resetCallback, width)); } else if (!ErrorCondition) { createHeaders(); createRows(); AddChild(new DialogGUIHorizontalLayout( width, 10, 0, wrenchPadding, TextAnchor.UpperRight, new DialogGUILabel(getMessage, notificationStyle, true, true) )); } }
/// <summary> /// Construct a view for the given model. /// </summary> /// <param name="m">Model object for which to make a view</param> /// <param name="reset">Function to call when the view needs to be re-initiated</param> public AstrogationView(AstrogationModel m, ResetCallback reset) : base( mainWindowMinWidth, mainWindowMinHeight, mainWindowSpacing, mainWindowPadding, TextAnchor.UpperCenter ) { model = m; resetCallback = reset; if (!ErrorCondition) { createHeaders(); createRows(); } AddChild(new DialogGUIHorizontalLayout( RowWidth, 10, 0, wrenchPadding, TextAnchor.UpperRight, new DialogGUILabel(getMessage, notificationStyle, true, true), iconButton(settingsIcon, settingsStyle, "Settings", toggleSettingsVisible) )); if (Settings.Instance.ShowSettings) { AddChild(new SettingsView(resetCallback)); } }
/// <summary> /// Construct a loader object for the given model /// </summary> /// <param name="m">Model object for us to manage</param> /// <param name="unReqNotif">Function to call if we trigger our own refresh without being asked (usually because a burn expired)</param> public AstrogationLoadBehaviorette(AstrogationModel m, LoadDoneCallback unReqNotif) { model = m; unrequestedLoadNotification = unReqNotif; // Watch for expiring burns StartBurnTimePolling(); }
/// <summary> /// Generate a string describing the state of a model. /// </summary> /// <param name="model">Model to examine</param> /// <returns> /// Description of error or warning if applicable, /// otherwise "Transfers from X". /// </returns> public static string ModelDescription(AstrogationModel model) { if (model == null) { return("Internal error: Model not found"); } else if (model.origin == null) { return("Internal error: Model's origin is null"); } else if (model.hyperbolicOrbit) { if (model.inbound) { return(Localizer.Format( "astrogator_inboundHyperbolicWarning", TheName(model.origin) )); } else { return(Localizer.Format( "astrogator_outboundHyperbolicError", TheName(model.origin) )); } } else if (model.badInclination) { return(Localizer.Format( "astrogator_highInclinationError", (AngleFromEquatorial(model.origin.GetOrbit().inclination *Mathf.Deg2Rad) * Mathf.Rad2Deg).ToString("0.0"), (AstrogationModel.maxInclination * Mathf.Rad2Deg).ToString("0") )); } else if (model.transfers.Count == 0) { return(Localizer.Format("astrogator_noTransfersError")); } else if (Landed(model.origin) || solidBodyWithoutVessel(model.origin)) { CelestialBody b = model.origin as CelestialBody; if (b == null) { b = model.origin.GetOrbit().referenceBody; } return(Localizer.Format( "astrogator_launchSubtitle", TheName(model.origin), FormatSpeed(DeltaVToOrbit(b), Settings.Instance.DisplayUnits) )); } else { return(Localizer.Format("astrogator_normalSubtitle", TheName(model.origin))); } }
AstrogatorMenu() : base() { model = new AstrogationModel( (ITargetable)FlightGlobals.ActiveVessel ?? (ITargetable)FlightGlobals.getMainBody()); loader = new AstrogationLoadBehaviorette(model, null); timeToWait = new List <DateTimeParts>(); cursorTransfer = 0; loader.TryStartLoad(model.origin, null, null, null); }
/// <summary> /// Initialize the plugin /// </summary> public Astrogator() : base() { model = new AstrogationModel(); loader = new AstrogationLoadBehaviorette(model, ResetViewBackground); }
/// <summary> /// Construct a loader object for the given model /// </summary> /// <param name="m">Model object for us to manage</param> /// <param name="unReqNotif">Function to call if we trigger our own refresh without being asked (usually because a burn expired)</param> public AstrogationLoadBehaviorette(AstrogationModel m, LoadDoneCallback unReqNotif) { model = m; unrequestedLoadNotification = unReqNotif; }