using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MLEM.Extensions; using MLEM.Font; using MLEM.Formatting; using MLEM.Formatting.Codes; using MLEM.Startup; using MLEM.Textures; namespace Demos { public class TextFormattingDemo : Demo { private const string Text = "MLEM's text formatting system allows for various formatting codes to be applied in the middle of a string. Here's a demonstration of some of them.\n\n" + "You can write in bold, italics, with an underline, strikethrough, with a drop shadow whose color and offset you can modify in each application of the code, or with various types of combined formatting codes.\n\n" + "You can apply custom colors to text, including all default MonoGame colors and inline custom colors.\n\n" + "You can also use animations like a wobbly one, as well as create custom ones using the Code class.\n\n" + "You can also display icons in your text!\n\n" + "Additionally, the text formatter has various methods for interacting with the text, like custom behaviors when hovering over certain parts, and more."; private const float Scale = 0.5F; private const float Width = 0.9F; private TextFormatter formatter; private TokenizedString tokenizedText; private GenericFont font; private bool drawBounds; public TextFormattingDemo(MlemGame game) : base(game) {} public override void LoadContent() { this.Game.Window.ClientSizeChanged += this.OnResize; // creating a new text formatter as well as a generic font to draw with this.formatter = new TextFormatter(); // GenericFont and its subtypes are wrappers around various font classes, including SpriteFont, MonoGame.Extended's BitmapFont and FontStashSharp // supplying a bold and italic version of the font here allows for the bold and italic formatting codes to be used this.font = new GenericSpriteFont( Demo.LoadContent("Fonts/TestFont"), Demo.LoadContent("Fonts/TestFontBold"), Demo.LoadContent("Fonts/TestFontItalic")); // adding the image code used in the example to it var testTexture = Demo.LoadContent("Textures/Test"); this.formatter.AddImage("grass", new TextureRegion(testTexture, 0, 0, 8, 8)); // tokenizing our text and splitting it to fit the screen // we specify our text alignment here too, so that all data is cached correctly for display this.tokenizedText = this.formatter.Tokenize(this.font, TextFormattingDemo.Text, TextAlignment.Center); this.tokenizedText.Split(this.font, this.GraphicsDevice.Viewport.Width * TextFormattingDemo.Width, TextFormattingDemo.Scale, TextAlignment.Center); } public override void DoDraw(GameTime time) { this.GraphicsDevice.Clear(Color.DarkSlateGray); this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise); // we draw the tokenized text in the center of the screen // since the text is already center-aligned, we only need to align it on the y axis here var size = this.tokenizedText.Measure(this.font) * TextFormattingDemo.Scale; var pos = new Vector2(this.GraphicsDevice.Viewport.Width / 2, (this.GraphicsDevice.Viewport.Height - size.Y) / 2); // draw bounds, which can be toggled with B in this demo if (this.drawBounds) { foreach (var token in this.tokenizedText.Tokens) { foreach (var area in token.GetArea(pos, TextFormattingDemo.Scale)) this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Black * 0.25F); } } // draw the text itself this.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, TextFormattingDemo.Scale, 0); this.SpriteBatch.End(); } public override void Update(GameTime time) { // update our tokenized string to animate the animation codes this.tokenizedText.Update(time); if (this.InputHandler.IsPressed(Keys.B)) this.drawBounds = !this.drawBounds; } public override void Clear() { base.Clear(); this.Game.Window.ClientSizeChanged -= this.OnResize; } private void OnResize(object sender, EventArgs e) { // re-split our text if the window resizes, since it depends on the window size // this doesn't require re-tokenization of the text, since TokenizedString also stores the un-split version this.tokenizedText.Split(this.font, this.GraphicsDevice.Viewport.Width * TextFormattingDemo.Width, TextFormattingDemo.Scale, TextAlignment.Center); } } }