bool updateTargetLine = false; // Indicate if target line needs updating

        #endregion Fields

        #region Constructors

        // Constructor
        // Give the navigator to which this control is for
        public Controls(Navigator navigator)
        {
            // Defaults window
            defaultWindow = new DefaultWindow(navigator);

            // Assign navigator field
            this.navigator = navigator;
            Debug.Log(this.navigator.ToString());

            // Controls window id
            id = GUIUtility.GetControlID(FocusType.Keyboard);

            // Initial time
            if (navigator.UT0 == 0) {
            UT0 = Planetarium.GetUniversalTime();
            } else {
            UT0 = navigator.UT0;
            }
            Debug.Log(UT0.ToString());

            // Off navigator control
            navigatorOff = Control.Default(navigator, this);

            // If the navigator doesn't have saved controls, return default
            if (String.IsNullOrEmpty(navigator.frames) ||
            String.IsNullOrEmpty(navigator.angle0s) ||
            String.IsNullOrEmpty(navigator.angle1s) ||
            String.IsNullOrEmpty(navigator.angle2s) ||
            String.IsNullOrEmpty(navigator.throttles) ||
            String.IsNullOrEmpty(navigator.sailons) ||
            String.IsNullOrEmpty(navigator.durations)) {
            ncontrols = 1;
            controls = new List<Control>();
            controls.Add(Control.Default(navigator, this));

            } else { // Otherwise, parse saved controls

            // Split into arrays
            var frameStrings = navigator.frames.Split(delimiter);
            var angle0Strings = navigator.angle0s.Split(delimiter);
            var angle1Strings = navigator.angle1s.Split(delimiter);
            var angle2Strings = navigator.angle2s.Split(delimiter);
            var throttleStrings = navigator.throttles.Split(delimiter);
            var durationStrings = navigator.durations.Split(delimiter);
            var sailonStrings = navigator.sailons.Split(delimiter);

            // Find number of controls
            ncontrols =
            Math.Min(frameStrings.Length,
                 Math.Min(angle0Strings.Length,
                      Math.Min(angle1Strings.Length,
                           Math.Min(angle2Strings.Length,
                            Math.Min(throttleStrings.Length,
                                 Math.Min(durationStrings.Length,
                                      sailonStrings.Length))))));

            // Initialize controls array
            controls = new List<Control>();

            // Populate controls
            for(var i = 0; i < ncontrols; i++) {
            var angles = new float [] { Utils.ParseSingle(angle0Strings[i]),
                        Utils.ParseSingle(angle1Strings[i]),
                        Utils.ParseSingle(angle2Strings[i]) };
            controls.Add(new Control(navigator,
                         this,
                         angles,
                         Utils.ParseSingle(throttleStrings[i]),
                         Utils.ParseBool(sailonStrings[i]),
                         Utils.ParseDouble(durationStrings[i]),
                         navigator.defaultIWarp,
                         frameStrings[i]));
            }
            }

            // Preview
            preview = new Preview(navigator);
        }
        // Constructor & calculate
        public void Propagate(Navigator navigator, Orbit orbit0, double UT0, double UTf, double dT, Control control, double m0in)
        {
            // Control parameters
            var throttle = control.throttle;
            var sailon = control.sailon;
            var frame = control.frame;

            // Update segment initial mass
            m0 = m0in;

            // Working orbit at each time step
            Orbit orbit = orbit0.Clone();

            // Number of time steps
            int nsteps = Convert.ToInt32(Math.Ceiling((UTf - UT0) / dT));

            // Last time step size
            double dTlast = (UTf - UT0) % dT;

            // Current universal time
            double UT;

            // Current mass
            double m0i = m0;

            // Reseting time step to sample orbits for saving
            double dTchoose = 0.0;

            // List of orbits to preview
            orbits = new List<Orbit>();

            // Add initial orbit
            orbits.Add(orbit0.Clone());

            // Iterate for nsteps
            for (int i = 0; i < nsteps; i++) {

            // Last step goes to UTf
            if (i == nsteps - 1) {
            dT = dTlast;
            UT = UTf;
            } else {
            UT = UT0 + i * dT;
            }

            // Spacecraft reference frame
            Quaternion sailFrame = frame.qfn(orbit, UT, control.angles);

            // Total deltaV vector
            Vector3d deltaVV = new Vector3d(0.0, 0.0, 0.0);

            // Accumulated mass change for all engines
            double dms = 0.0;

            // Iterate over engines
            foreach (var pe in navigator.persistentEngines) {

            // Only count thrust of engines that are not shut down in preview
            if (pe.engine.getIgnitionState) {

            // Thrust unit vector
            Vector3d thrustUV = sailFrame * new Vector3d(0.0, 1.0, 0.0);

            // Isp: Currently vacuum. TODO: calculate at current air pressure
            float isp = pe.engine.atmosphereCurve.Evaluate(0);

            // Thrust vector
            float thrust = throttle * pe.engine.maxThrust;

            // Calculate deltaV vector
            double demandMass;
            deltaVV += pe.CalculateDeltaVV(m0i, dT, thrust, isp, thrustUV, out demandMass);

            // Update mass usage
            dms += demandMass * pe.densityAverage;
            }
            }

            // Iterate over sails
            if (sailon) {
            foreach (var s in navigator.solarSails) {

            // Check if sail in sun
            double sunlightFactor = 1.0;
            if (!SolarSailPart.inSun(orbit, UT)) {
                sunlightFactor = 0.0;
            }

            // Normal vector
            Vector3d n = sailFrame * new Vector3d(0.0, 1.0, 0.0);

            // Force on sail
            Vector3d solarForce = SolarSailPart.CalculateSolarForce(s, orbit, n, UT) * sunlightFactor;

            // Sail acceleration
            Vector3d solarAccel = solarForce / m0i / 1000.0;

            // Update deltaVV
            deltaVV += solarAccel * dT;
            }
            }

            // Update starting mass for next time step
            m0i -= dms;

            // Update

            // Update orbit
            orbit.Perturb(deltaVV, UT);

            // Increment time step at which to sample orbits
            dTchoose += dT;

            // Orbit period
            double TP = orbit.period;

            // Decide whether to add orbit to list of orbits to draw
            if (i == nsteps - 1) { // Always add last orbit
            orbits.Add(orbit.Clone());
            } else if (dTchoose >= TP / 360) { // If 1/360th of current period passed, add orbit
            orbits.Add(orbit.Clone());
            // Reset dTchoose
            dTchoose = 0.0;
            }
            }

            // Update final mass
            m1 = m0i;
        }
 public FrameWindow(Control control)
 {
     // Rectangle object
     frameWindowPos = new Rect(705, 50, 0, 0);
     // Frame window ID
     frameID = GUIUtility.GetControlID(FocusType.Keyboard);
     // Initialize frame selection window
     RenderingManager.AddToPostDrawQueue(3, new Callback(DrawFrameWindow));
     this.control = control;
 }
        GameObject obj; // Game object of line

        #endregion Fields

        #region Constructors

        public PreviewSegment(Navigator navigator, Orbit orbitInitial, double UT0, double UTf, Control control, Color color, double m0in)
        {
            this.UT0 = UT0;
            this.UTf = UTf;
            dT = TimeWarp.fixedDeltaTime * control.warp;

            // Update preview orbits
            this.Propagate(navigator, orbitInitial, UT0, UTf, dT, control, m0in);
            orbit0 = orbits[0];
            orbitf = orbits.Last();

            // Initialize LineRenderer

            // Remove old line
            if (line != null) {
            UnityEngine.Object.Destroy(line);
            }
            // Create new one
            obj = new GameObject("Preview segment");
            line = obj.AddComponent<LineRenderer>();
            line.useWorldSpace = false;
            obj.layer = 10; // Map view
            line.material = MapView.fetch.orbitLinesMaterial;
            line.SetColors(color, color);
            line.SetVertexCount(orbits.Count);
            // Calculate relative position vectors
            relativePoints = new Vector3d[orbits.Count];
            for(var i = 0; i < orbits.Count; i++) {
            double UTi = orbits[i].epoch;
            relativePoints[i] = orbits[i].getRelativePositionAtUT(UTi).xzy;
            }
        }