Example #1
0
    /// <summary>
    /// show error code
    /// </summary>
    /// <param name="error"></param>
    public void ErrorCode(string error)
    {
        m_textDisplay.Clear();

        m_textDisplay.DrawText(0, 0, error);
        m_textDisplay.Refresh();

        m_status = Defines.PROGRAM_STATUS_ERROR;
    }
Example #2
0
    /// <summary>
    /// 切换至文本模式(带光标)
    /// </summary>
    public void TextMode()
    {
        m_graphDisplay.enabled = false;
        m_textDisplay.enabled  = true;

        m_textDisplay.Clear();
    }
Example #3
0
 public static void Clear()
 {
     if (!display.IsDefault())
     {
         display.Clear();
     }
 }
Example #4
0
    private IEnumerator DoDisplay(BeatData data)
    {
        _output.Clear();

        while (_output.IsBusy)
        {
            yield return(null);
        }

        _output.Display(data.DisplayText);

        while (_output.IsBusy)
        {
            yield return(null);
        }
    }
Example #5
0
    private IEnumerator DoDisplay(BeatData data)
    {
        _output.Clear();

        while (_output.IsBusy)
        {
            yield return(null);
        }

        _output.Display(data.DisplayText);

        while (_output.IsBusy)
        {
            yield return(null);
        }

        for (int count = 0; count < data.Decision.Count; ++count)
        {
            ChoiceData choice = data.Decision[count];
            _output.Display(string.Format("{0}: {1}", (count + 1), choice.DisplayText));

            while (_output.IsBusy)
            {
                yield return(null);
            }
        }

        if (data.Decision.Count > 0)
        {
            _output.ShowWaitingForInput();
        }
    }
Example #6
0
 private void BorrarUno_Click(object sender, EventArgs e)
 {
     if (TextDisplay.Text.Length > 1)
     {
         TextDisplay.Text = TextDisplay.Text.Substring(0, TextDisplay.Text.Length - 1);
     }
     else
     {
         TextDisplay.Clear();
     }
 }
        private void btnBacksp_Click(object sender, RoutedEventArgs e)
        {
            float  length = TextDisplay.Text.Length - 1;
            string text   = TextDisplay.Text;

            TextDisplay.Clear();
            for (int i = 0; i < length; i++)
            {
                TextDisplay.Text = TextDisplay.Text + text[i];
            }
        }
Example #8
0
    // Starts coroutines in order to scroll beat text and choices on the screen
    // success parameter is used for certain choice responses
    private IEnumerator DoDisplay(BeatData data, bool showAnimations, bool success = false)
    {
        if(showAnimations) 
        {
            HUD.instance.dialogueMenu.SetActive();
            yield return _waitInitial;
        } 
        else 
        {
            HUD.instance.dialogueMenu.HideChoicesPanel();
        }

        NPC npcSpeaking = PlayerController.instance.npcSpeaking;
        TextDisplay npcSpeech = HUD.instance.dialogueMenu.NpcSpeechText;
        npcSpeech.Clear();

        while (npcSpeech.IsBusy)
        {
            yield return null;
        }

        if(data.DisplayTextType == SpeechType.FlatterResponse || data.DisplayTextType == SpeechType.ThreatenResponse ||
                data.DisplayTextType == SpeechType.BribeResponse) 
        {
            HUD.instance.dialogueMenu.ShowNpcSpeech(data.GetDisplayText(_textData, success), showAnimations);
        } 
        else if(data.DisplayTextType == SpeechType.RumourStart) 
        {
            string text;
            if(success) 
            {
                text = unlockedRumours[npcSpeaking].StartText;
            } 
            else if(HasRumourAvailable(npcSpeaking)) 
            {
                // If there are rumours available but the NPC disposition is too low then give a rejection line
                text = _textData.GetRandomRumourFail();
            } 
            else 
            {
                // If there aren't any rumours available give a neutral apology
                text = _textData.GetRandomRumourUnknown();
            }
            HUD.instance.dialogueMenu.ShowNpcSpeech(text, showAnimations);
        }
        else if(data.DisplayTextType == SpeechType.RumourEnd) 
        {
            Rumour rumour = GetRumourForTargetNpc(npcSpeaking);
            HUD.instance.dialogueMenu.ShowNpcSpeech(rumour.EndText, showAnimations);
            CompleteRumour(rumour);
        }
        else 
        {
            HUD.instance.dialogueMenu.ShowNpcSpeech(data.GetDisplayText(_textData, npcSpeaking.DispositionType), showAnimations);
        }
        // npcSpeech.Display(data.GetDisplayText(npcSpeaking.disposition));

        // On the greeting beat wait until the speech has finished before showing the other panels
        while(npcSpeech.IsBusy)
        {
            yield return null;
        }

        if(showAnimations) HUD.instance.dialogueMenu.ShowNpcInfo(npcSpeaking);
        // yield return _wait;

        // Copy choices from other beat if needed
        if(data.CopyChoicesFromBeat) {
            int id = data.BeatIdToCopyFrom;
            data.Decision = _data.GetBeatById(id).Decision;
        }

        // Set choices
        List<ChoiceData> choices = new List<ChoiceData>();;

        int correctChoice = Random.Range(0, data.Decision.Count - 1); // -1 to account for the nevermind choice
        List<string> usedTextLines = new List<string>(); // Keep track of use choice text to avoid getting the same line twice
        for(int i = 0; i < data.Decision.Count; i++) 
        {
            data.Decision[i].IsCorrectChoice = i == correctChoice;

            switch(data.Decision[i].TextType) 
            {
                case ChoiceTextType.RandomFlatter:
                    string text;
                    do 
                    {
                        text = _textData.GetRandomFlattery(npcSpeaking, i == correctChoice);
                    } 
                    while(usedTextLines.Contains(text));
                    
                    usedTextLines.Add(text);
                    data.Decision[i].DisplayText = text;
                    break;
                case ChoiceTextType.RandomThreaten:
                    do 
                    {
                        text = _textData.GetRandomThreaten(npcSpeaking, i == correctChoice);
                    } 
                    while(usedTextLines.Contains(text));
                    
                    usedTextLines.Add(text);
                    data.Decision[i].DisplayText = text;
                    break;
                case ChoiceTextType.BribeAmount:
                    data.Decision[i].DisplayText = LevelManager.instance.BribeGoldAmount(i) + " gold";
                    break;
                case ChoiceTextType.RumourMid:
                    Rumour rumour = GetRumourForTargetNpc(npcSpeaking);
                    if(rumour != null) 
                    {
                        data.Decision[i].DisplayText = rumour.MiddleText;
                        choices.Add(data.Decision[i]);
                    }
                    break;
            }

            // Add all choices other than rumour as that is handled in the switch
            if(data.Decision[i].TextType != ChoiceTextType.RumourMid) 
            {
                choices.Add(data.Decision[i]);
            }
        }

        _currentChoices = choices.ToArray();
        HUD.instance.dialogueMenu.ShowChoicesPanel(npcSpeaking, _currentChoices);

        // for (int count = 0; count < data.Decision.Count; ++count)
        // {
        //     ChoiceData choice = data.Decision[count];
        //     npcSpeech.Display(string.Format("{0}: {1}", (count + 1), choice.DisplayText));

        //     while (npcSpeech.IsBusy)
        //     {
        //         yield return null;
        //     }
        // }

        // if(data.Decision.Count > 0)
        // {
        //     npcSpeech.ShowWaitingForInput();
        // }
    }
Example #9
0
        /// <summary>
        /// Draws all the physics bodies and UI elements.
        /// </summary>
        private unsafe void DrawFrame(TimeStep timeStep, FpsManager frameTimer)
        {
            _textDisplay.Clear();

            RectangleD cameraBounds = _camera.Bounds;

            IGravitationalBody target = _gravitationalBodies[_targetIndex];
            var targetSpaceCraft      = target as SpaceCraftBase;

            // If openCL is supported render all cl bodies
            if (_renderingType == RenderingType.OpenCLHardware ||
                _renderingType == RenderingType.OpenCLSoftware)
            {
                _gpuClear.RenderCl(_clProxy);

                foreach (MassiveBodyBase renderable in _massiveBodies)
                {
                    if (renderable.Visibility(cameraBounds) > 0)
                    {
                        renderable.RenderCl(_clProxy, cameraBounds, _sun);
                    }
                }

                int[] frameData = _clProxy.ReadIntBuffer("image", RenderUtils.ScreenArea);

                var rect = new Rectangle(0, 0, _imageBitmap.Width, _imageBitmap.Height);

                BitmapData bmpData = _imageBitmap.LockBits(rect, ImageLockMode.WriteOnly,
                                                           PixelFormat.Format32bppArgb);

                Marshal.Copy(frameData, 0, bmpData.Scan0, RenderUtils.ScreenArea);

                var ptr = (byte *)bmpData.Scan0;

                // Hack to force full alpha for now
                for (int i = 0; i < RenderUtils.ScreenArea; i++)
                {
                    ptr[i * 4 + 3] = 255;
                }

                _imageBitmap.UnlockBits(bmpData);
            }
            else
            {
                // Fall back to gdi for cl renderables
                using (var graphics = Graphics.FromImage(_imageBitmap))
                {
                    graphics.Clear(Color.Black);

                    _camera.ApplyScreenRotation(graphics);

                    foreach (MassiveBodyBase renderable in _massiveBodies)
                    {
                        if (renderable.Visibility(cameraBounds) > 0)
                        {
                            renderable.RenderGdiFallback(graphics, cameraBounds, _sun);
                        }
                    }
                }
            }

            // Draw all orbit traces, spacecrafts, and GDI objects
            using (Graphics graphics = RenderUtils.GetContext(false, _imageBitmap))
            {
                _camera.ApplyScreenRotation(graphics);

                //RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(0, -10e12), new DVector2(0, 10e12), Color.FromArgb(40, 255, 255, 255));
                //RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(-10e12, 0), new DVector2(10e12, 0), Color.FromArgb(40, 255, 255, 255));

                // Draw all massive body orbit traces
                foreach (MassiveBodyBase massiveBody in _massiveBodies)
                {
                    if (massiveBody is Sun)
                    {
                        continue;
                    }

                    massiveBody.RenderGdi(graphics, _camera);
                }

                graphics.ResetTransform();

                // Draw structures
                foreach (StructureBase structure in _structures)
                {
                    structure.RenderGdi(graphics, _camera);
                }

                // Draw spacecraft
                foreach (SpaceCraftBase spaceCraft in _spaceCrafts)
                {
                    spaceCraft.RenderGdi(graphics, _camera);
                }
            }

            // Draw all GUI elements (higher quality)
            using (Graphics graphics = RenderUtils.GetContext(true, _imageBitmap))
            {
                double throttle = 0;

                if (targetSpaceCraft != null)
                {
                    throttle = targetSpaceCraft.Throttle;
                }

                foreach (IGauge gauge in _gauges)
                {
                    if (targetSpaceCraft != null)
                    {
                        gauge.Update(_gravitationalBodies[_targetIndex].GetRelativePitch(), throttle / 100.0);
                    }

                    gauge.Render(graphics, cameraBounds);
                }

                _eventManager.Render(graphics);

                var elapsedTime = TimeSpan.FromSeconds(_totalElapsedSeconds - ClockDelayInSeconds);

                int elapsedYears = elapsedTime.Days / 365;
                int elapsedDays  = elapsedTime.Days % 365;

                DateTime localTime = _originTime + elapsedTime;

                // Main timing display
                _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                {
                    $"Origin Time: {localTime.ToShortDateString()} {localTime.ToShortTimeString()}",
                    $"Elapsed Time: Y:{elapsedYears} D:{elapsedDays} H:{elapsedTime.Hours} M:{elapsedTime.Minutes} S:{elapsedTime.Seconds}",
                    $"Update Speed: {timeStep.Multiplier}"
                });

                // Target display
                _textDisplay.AddTextBlock(StringAlignment.Center, string.Format("Target: {0}", target));

                // FPS
                _textDisplay.AddTextBlock(StringAlignment.Far, "FPS: " + frameTimer.CurrentFps);

                double targetVelocity = target.GetRelativeVelocity().Length();

                // Info for altitude
                var altitudeInfo = new List <string> {
                    "Altitude: " + UnitDisplay.Distance(target.GetRelativeAltitude())
                };

                // Add downrange if spacecraft exists
                if (targetSpaceCraft != null)
                {
                    double downrangeDistance = targetSpaceCraft.GetDownrangeDistance(_structures[0].Position);

                    altitudeInfo.Add("Downrange: " + UnitDisplay.Distance(downrangeDistance));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, altitudeInfo);

                // Info for speed / acceleration
                var movementInfo = new List <string>
                {
                    "Relative Speed: " + UnitDisplay.Speed(targetVelocity, false),
                    "Relative Acceleration: " + UnitDisplay.Acceleration(target.GetRelativeAcceleration().Length()),
                };

                // Add angle of attack if it exists
                if (targetSpaceCraft != null)
                {
                    movementInfo.Add("Angle of Attack: " + UnitDisplay.Degrees(targetSpaceCraft.GetAlpha()));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, movementInfo);

                var forceInfo = new List <string> {
                    "Mass: " + UnitDisplay.Mass(target.Mass)
                };

                // Add additional forces
                if (targetSpaceCraft != null)
                {
                    DVector2 dragForce = targetSpaceCraft.AccelerationD * targetSpaceCraft.Mass;
                    DVector2 liftForce = targetSpaceCraft.AccelerationL * targetSpaceCraft.Mass * Math.Cos(targetSpaceCraft.Roll);

                    forceInfo.Add("Thrust: " + UnitDisplay.Force(targetSpaceCraft.Thrust));
                    forceInfo.Add("Drag: " + UnitDisplay.Force(dragForce.Length()));
                    forceInfo.Add("Lift: " + UnitDisplay.Force(liftForce.Length()));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, forceInfo);

                // Don't show apogee/perigee info for the sun
                if (!(target is Sun))
                {
                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        "Apogee: " + UnitDisplay.Distance(target.Apogee),
                        "Perigee: " + UnitDisplay.Distance(target.Perigee)
                    });
                }

                // Add atmospheric info if the spaceship is the target
                if (targetSpaceCraft != null)
                {
                    double density         = targetSpaceCraft.GravitationalParent.GetAtmosphericDensity(target.GetRelativeAltitude());
                    double dynamicPressure = 0.5 * density * targetVelocity * targetVelocity;

                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        "Air Density: " + UnitDisplay.Density(density),
                        "Dynamic Pressure: " + UnitDisplay.Pressure(dynamicPressure),
                        "Heating Rate: " + UnitDisplay.Heat(targetSpaceCraft.HeatingRate)
                    });
                }

                _textDisplay.Draw(graphics);
            }
        }
Example #10
0
        public void Run()
        {
            double time   = 0;
            var    random = new Random();

            while (_window.IsOpen)
            {
                // Normal SFML stuff
                _window.DispatchEvents();
                _window.Clear(Color.White);

                // Clear the TextDisplay to a Character, this is not required but I do it anyways
                _example.Clear(Character.Blank);

                // Lets leave a border to demo regions
                var region = _example.Region(1, 1, Width - 2, Height - 2);

                // Render our fractal, I think I got this code from Wikipedia and added zooming
                for (var y = 0; y < Height; y++)
                {
                    for (var x = 0; x < Width; x++)
                    {
                        var posX = (double)x / Width;
                        var posY = (double)y / Height;

                        var x0 = (posX * 3.5) - 2.5;
                        var y0 = (posY * 2.0) - 1;

                        // Zooming
                        x0 /= 1.5f + Math.Sin(time) * 0.5f;
                        y0 /= 1.5f + Math.Sin(time) * 0.5f;

                        double xx = 0;
                        double yy = 0;

                        const int maxIteration = 24;
                        var       iteration    = 0;

                        while (xx * xx + yy * yy < 2 * 2 && iteration < maxIteration)
                        {
                            var xtemp = xx * xx - yy * yy + x0;
                            yy = 2 * xx * yy + y0;
                            xx = xtemp;

                            iteration++;
                        }

                        var colorPercentage = (double)iteration / maxIteration;
                        var color           = (byte)(colorPercentage * 255);

                        // Modifying the TextDisplay per Character, through a region
                        region.Set(x, y, new Character(random.Next(255), color - 128, color));
                    }
                }

                // Effect that brightens the background color
                var effect = _example.Effect((x, y, c) => new Character(c.Glyph, c.Foreground, Math.Max(c.Background - 128, 0)));

                // Render a box with our effect
                effect.DrawBox(2, 2, 19, 5, TextExtensions.SingleBox, new Character(foreground: 255));

                // And then we render our message onto the box
                _example.DrawText(5, 4, "Hello, world!", new Character(foreground: 255));

                // Render the TextDisplay to the SFML window
                _window.Draw(_example);

                // And finally have SFML display it to us
                _window.Display();

                time += 0.1;
            }
        }
 public void Clear()
 {
     textDisplay.Clear();
 }
        /// <summary>
        /// Draws all the physics bodies and UI elements.
        /// </summary>
        private unsafe void DrawFrame(TimeStep timeStep, FpsManager frameTimer)
        {
            _textDisplay.Clear();

            // check for global events
            _eventManager.CheckForGlobalEvents(this);

            RectangleD cameraBounds = _camera.Bounds;

            IGravitationalBody target = _gravitationalBodies[_targetIndex];
            var targetSpaceCraft      = target as SpaceCraftBase;

            // If openCL is supported render all cl bodies
            if (_renderingType == RenderingType.OpenCLHardware ||
                _renderingType == RenderingType.OpenCLSoftware)
            {
                _gpuClear.RenderCl(_clProxy);

                foreach (MassiveBodyBase renderable in _massiveBodies)
                {
                    if (renderable.Visibility(cameraBounds) > 0)
                    {
                        renderable.RenderCl(_clProxy, _camera, _sun);
                    }
                }

                int[] frameData = _clProxy.ReadIntBuffer("image", RenderUtils.ScreenArea);

                var rect = new Rectangle(0, 0, _imageBitmap.Width, _imageBitmap.Height);

                BitmapData bmpData = _imageBitmap.LockBits(rect, ImageLockMode.WriteOnly,
                                                           PixelFormat.Format32bppArgb);

                Marshal.Copy(frameData, 0, bmpData.Scan0, RenderUtils.ScreenArea);

                var ptr = (byte *)bmpData.Scan0;

                // Hack to force full alpha for now
                for (int i = 0; i < RenderUtils.ScreenArea; i++)
                {
                    ptr[i * 4 + 3] = 255;
                }

                _imageBitmap.UnlockBits(bmpData);
            }
            else
            {
                // Fall back to gdi for cl renderables
                using (var graphics = Graphics.FromImage(_imageBitmap))
                {
                    graphics.Clear(Color.Black);

                    _camera.ApplyScreenRotation(graphics);

                    foreach (MassiveBodyBase renderable in _massiveBodies)
                    {
                        if (renderable.Visibility(cameraBounds) > 0)
                        {
                            renderable.RenderGdiFallback(graphics, _camera, _sun);
                        }
                    }
                }
            }

            // Draw all orbit traces, spacecrafts, and GDI objects
            using (Graphics graphics = RenderUtils.GetContext(false, _imageBitmap))
            {
                _camera.ApplyScreenRotation(graphics);

                // Draw all massive body orbit traces
                foreach (MassiveBodyBase massiveBody in _massiveBodies)
                {
                    if (massiveBody is Sun)
                    {
                        continue;
                    }

                    massiveBody.RenderGdi(graphics, _camera);
                }

                graphics.ResetTransform();

                // Draw structures
                foreach (StructureBase structure in _structures)
                {
                    structure.RenderGdi(graphics, _camera);
                }

                _spaceCraftManager.Render(graphics, _camera);
            }

            // Draw all GUI elements (higher quality)
            using (Graphics graphics = RenderUtils.GetContext(true, _imageBitmap))
            {
                double throttle = 0;

                if (targetSpaceCraft != null)
                {
                    throttle = targetSpaceCraft.Throttle;

                    // TODO: render PIP
                    //int width = RenderUtils.ScreenWidth;
                    //int height = RenderUtils.ScreenHeight;
                    //Rectangle rectPip = new Rectangle(width - 220, 100, 200, height - 300);
                    //graphics.DrawRectangle(Pens.White, rectPip);

                    //_pipCam.ApplyScreenRotation(graphics);
                    //_spaceCraftManager.Render(graphics, _pipCam);
                }

                double pitch           = 0.0;
                double flightPathAngle = 0.0;
                foreach (IGauge gauge in _gauges)
                {
                    if (targetSpaceCraft != null)
                    {
                        if (_targetInOrbit && _rotateInOrbit)
                        {
                            pitch = _gravitationalBodies[_targetIndex].Pitch;
                        }
                        else
                        {
                            pitch = _gravitationalBodies[_targetIndex].GetRelativePitch();
                        }

                        flightPathAngle = pitch - targetSpaceCraft.GetAlpha();
                        gauge.Update(pitch, throttle / 100.0, flightPathAngle);
                    }

                    gauge.Render(graphics, cameraBounds);
                }

                _eventManager.Render(graphics);

                var elapsedTime = TimeSpan.FromSeconds(_totalElapsedSeconds - _clockDelay);

                int elapsedYears = elapsedTime.Days / 365;
                int elapsedDays  = elapsedTime.Days % 365;

                DateTime localTime = _originTime + elapsedTime;

                // Main timing display
                _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                {
                    //$"Origin Time: {localTime.ToShortDateString()} {localTime.ToShortTimeString()}",
                    $"Origin Time: {string.Format("{0}-{1}-{2:D2}", localTime.Date.Year, localTime.Date.Month, localTime.Date.Day)} {localTime.ToShortTimeString()}",
                    //$"Elapsed Time: Y:{elapsedYears} D:{elapsedDays} H:{elapsedTime.Hours} M:{elapsedTime.Minutes} S:{Math.Round(elapsedTime.TotalSeconds % 60)}",
                    $"Elapsed Time: Y:{elapsedYears} D:{elapsedDays} H:{elapsedTime.Hours} M:{elapsedTime.Minutes} S:{elapsedTime.Seconds}",
                    $"Update Speed: {timeStep.Multiplier}"
                });

                // Target display
                _textDisplay.AddTextBlock(StringAlignment.Center, string.Format("Target: {0}", target));

                // FPS
                _textDisplay.AddTextBlock(StringAlignment.Far, "FPS: " + frameTimer.CurrentFps);

                double targetVelocity   = target.GetRelativeVelocity().Length();
                double inertialVelocity = target.GetInertialVelocity().Length();

                // Info for altitude
                // double altitude = target.GetRelativeAltitude();
                // double altitude = target.GetRelativeAltitude() + 82.5;    // Starship Mk1
                double altitude     = target.GetRelativeAltitude() - 111.4; // Starship + Super Heavy
                var    altitudeInfo = new List <string> {
                    "Altitude: " + UnitDisplay.Distance(altitude)
                };

                // Add downrange if spacecraft exists
                if (targetSpaceCraft != null)
                {
                    double downrangeDistance = targetSpaceCraft.GetDownrangeDistance(_structures[0].Position);

                    altitudeInfo.Add("Downrange: " + UnitDisplay.Distance(downrangeDistance));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, altitudeInfo);

                // Info for speed / acceleration
                var movementInfo = new List <string>
                {
                    "Inertial Velocity: " + UnitDisplay.Speed(targetVelocity, useKmh),
                    "Orbital Velocity: " + UnitDisplay.Speed(inertialVelocity, useKmh),
                    "Inertial Acceleration: " + UnitDisplay.Acceleration(target.GetRelativeAcceleration().Length()),
                    "Orbital Acceleration: " + UnitDisplay.Acceleration(target.GetInertialAcceleration().Length())
                };

                double lateralVelocity = target.GetLateralVelocity().Length();
                if (lateralVelocity > 0)
                {
                    double lateralPosition = target.GetLateralPosition().Length();
                    altitudeInfo.Add("Crossrange: " + UnitDisplay.Distance(lateralPosition));

                    movementInfo.Add("Lateral Velocity: " + UnitDisplay.Speed(lateralVelocity, useKmh));
                    movementInfo.Add("Lateral Acceleration: " + UnitDisplay.Acceleration(target.GetLateralAcceleration().Length()));
                }

                // Add angle of attack if it exists
                if (targetSpaceCraft != null)
                {
                    movementInfo.Add("Angle of Attack: " + UnitDisplay.AoA(targetSpaceCraft.GetAlpha()));

                    // calculate the current inclination
                    double G      = 6.67408E-11;
                    double M      = target.GravitationalParent.Mass;
                    double μ      = G * M;
                    double R      = target.GravitationalParent.SurfaceRadius;
                    double apogee = target.Apoapsis;
                    if (initialPerigee == 0)
                    {
                        initialPerigee = target.Periapsis;
                    }
                    double Ra = R + apogee;
                    double Rp = R + initialPerigee;
                    double e  = 1 - 2 / ((Ra / Rp) + 1);
                    double ω  = 0;
                    double f  = 0;

                    // orbital period
                    double a           = (initialPerigee + R * 2 + apogee) / 2;
                    double P           = 2 * Math.PI * Math.Pow(Math.Pow(a, 3) / μ, 0.5);
                    double n           = 2 * Math.PI / P;
                    double Δi          = 2 * Math.Asin(lateralVelocity * (1 + e * Math.Cos(f)) / (Math.Pow(1 - Math.Pow(e, 2), 0.5) * Math.Cos(ω + f) * n * a * 2));
                    double inclination = launchInclination * MathHelper.DegreesToRadians - Δi;
                    movementInfo.Add("Inclination: " + UnitDisplay.Degrees(inclination));

                    double speedOfSound = targetSpaceCraft.GravitationalParent.GetSpeedOfSound(target.GetRelativeAltitude());
                    if (speedOfSound > 0)
                    {
                        double machNumber = targetVelocity / speedOfSound;
                        movementInfo.Add("Mach number: " + UnitDisplay.Mach(machNumber));
                    }
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, movementInfo);

                var forceInfo = new List <string> {
                    "Mass: " + UnitDisplay.Mass(target.Mass)
                };

                // Add additional forces
                if (targetSpaceCraft != null)
                {
                    DVector2 dragForce = targetSpaceCraft.AccelerationD * targetSpaceCraft.Mass;
                    DVector2 liftForce = targetSpaceCraft.AccelerationL * targetSpaceCraft.Mass;
                    if (Settings.Default.UseTheTurnForce)
                    {
                        liftForce *= Math.Cos(targetSpaceCraft.Roll);
                    }

                    forceInfo.Add("Thrust: " + UnitDisplay.Force(targetSpaceCraft.Thrust));
                    forceInfo.Add("Drag: " + UnitDisplay.Force(dragForce.Length()));
                    forceInfo.Add("Lift: " + UnitDisplay.Force(liftForce.Length()));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, forceInfo);

                // Don't show Apoapsis/Periapsis info for the sun
                if (!(target is Sun) && target.GravitationalParent != null)
                {
                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        $"{target.GravitationalParent.ApoapsisName}: {UnitDisplay.Distance(target.Apoapsis)}",
                        $"{target.GravitationalParent.PeriapsisName}: {UnitDisplay.Distance(target.Periapsis)}",
                    });
                }

                // Add atmospheric info if the spaceship is the target
                if (targetSpaceCraft != null && targetSpaceCraft.GravitationalParent != null)
                {
                    double density         = targetSpaceCraft.GravitationalParent.GetAtmosphericDensity(target.GetRelativeAltitude());
                    double dynamicPressure = 0.5 * density * targetVelocity * targetVelocity;

                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        "Air Density: " + UnitDisplay.Density(density),
                        "Dynamic Pressure: " + UnitDisplay.Pressure(dynamicPressure),
                        "Heat Flux: " + UnitDisplay.Heat(targetSpaceCraft.HeatingRate)
                    });
                }

                _textDisplay.Draw(graphics);
            }
        }