using Barotrauma.IO; using FarseerPhysics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Text; namespace Barotrauma { static class WikiImage { public static Rectangle CalculateBoundingBox(Character character) { Rectangle boundingBox = new Rectangle(character.WorldPosition.ToPoint(), Point.Zero); void addPointsToBBox(float extentX, float extentY, Vector2 worldPos, Vector2 origin, float rotation) { float sinRotation = (float)Math.Sin((double)rotation); float cosRotation = (float)Math.Cos((double)rotation); origin = new Vector2( origin.X * cosRotation + origin.Y * sinRotation, origin.X * sinRotation - origin.Y * cosRotation); var limbPos = worldPos.ToPoint(); boundingBox.AddPoint(limbPos); Vector2 xExtend = new Vector2((extentX * cosRotation), (extentX * sinRotation)); Vector2 yExtend = new Vector2((extentY * sinRotation), (-extentY * cosRotation)); boundingBox.AddPoint(limbPos + (xExtend + yExtend - origin).ToPoint()); boundingBox.AddPoint(limbPos + (xExtend - yExtend - origin).ToPoint()); boundingBox.AddPoint(limbPos + (-xExtend - yExtend - origin).ToPoint()); boundingBox.AddPoint(limbPos + (-xExtend + yExtend - origin).ToPoint()); } foreach (Limb limb in character.AnimController.Limbs) { if (limb.ActiveSprite == null) { continue; } float extentX = (float)limb.ActiveSprite.size.X * limb.Scale * limb.TextureScale * 0.5f; //extentX = ConvertUnits.ToDisplayUnits(extentX); float extentY = (float)limb.ActiveSprite.size.Y * limb.Scale * limb.TextureScale * 0.5f; //extentY = ConvertUnits.ToDisplayUnits(extentY); Vector2 origin = (limb.ActiveSprite.Origin - (limb.ActiveSprite.SourceRect.Size.ToVector2() * 0.5f)) * limb.Scale * limb.TextureScale; addPointsToBBox(extentX, extentY, limb.WorldPosition, origin, limb.body.Rotation); } if (character.Inventory != null) { foreach (var item in character.Inventory.AllItems) { if (item?.Sprite != null && item?.body != null) { float extentX = (float)item.Sprite.size.X * item.Scale * 0.5f; //extentX = ConvertUnits.ToDisplayUnits(extentX); float extentY = (float)item.Sprite.size.Y * item.Scale * 0.5f; //extentY = ConvertUnits.ToDisplayUnits(extentY); Vector2 origin = (item.Sprite.Origin - (item.Sprite.SourceRect.Size.ToVector2() * 0.5f)) * item.Scale; addPointsToBBox(extentX, extentY, item.WorldPosition, origin, item.body.Rotation); } } } boundingBox.X -= 25; boundingBox.Y -= 25; boundingBox.Width += 50; boundingBox.Height += 50; return boundingBox; } public static void Create(Character character) { Rectangle boundingBox = CalculateBoundingBox(character); int texWidth = Math.Clamp((int)(boundingBox.Width * 2.5f), 512, 4096); float zoom = (float)texWidth / (float)boundingBox.Width; int texHeight = (int)(zoom * boundingBox.Height); Camera cam = new Camera(); cam.SetResolution(new Point(texWidth, texHeight)); cam.MaxZoom = zoom; cam.MinZoom = zoom * 0.5f; cam.Zoom = zoom; cam.Position = boundingBox.Center.ToVector2(); cam.UpdateTransform(false); using (RenderTarget2D rt = new RenderTarget2D( GameMain.Instance.GraphicsDevice, texWidth, texHeight, false, SurfaceFormat.Color, DepthFormat.None)) { using (SpriteBatch spriteBatch = new SpriteBatch(GameMain.Instance.GraphicsDevice)) { Viewport prevViewport = GameMain.Instance.GraphicsDevice.Viewport; GameMain.Instance.GraphicsDevice.Viewport = new Viewport(0, 0, texWidth, texHeight); GameMain.Instance.GraphicsDevice.SetRenderTarget(rt); GameMain.Instance.GraphicsDevice.Clear(Color.Transparent); spriteBatch.Begin(SpriteSortMode.BackToFront, transformMatrix: cam.Transform); character.Draw(spriteBatch, cam); if (character.Inventory != null) { foreach (var item in character.Inventory.AllItems) { if (item != null) { item.Draw(spriteBatch, false, false); item.Draw(spriteBatch, false, true); } } } spriteBatch.End(); GameMain.Instance.GraphicsDevice.SetRenderTarget(null); GameMain.Instance.GraphicsDevice.Viewport = prevViewport; using (FileStream fs = File.Open("wikiimage.png", System.IO.FileMode.Create)) { rt.SaveAsPng(fs, texWidth, texHeight); } } } } public static void Create(Submarine sub) { int width = 4096; int height = 4096; Rectangle subDimensions = sub.CalculateDimensions(false); Vector2 viewPos = subDimensions.Center.ToVector2(); float scale = Math.Min(width / (float)subDimensions.Width, height / (float)subDimensions.Height); var viewMatrix = Matrix.CreateTranslation(new Vector3(width / 2.0f, height / 2.0f, 0)); var transform = Matrix.CreateTranslation( new Vector3(-viewPos.X, viewPos.Y, 0)) * Matrix.CreateScale(new Vector3(scale, scale, 1)) * viewMatrix; using (RenderTarget2D rt = new RenderTarget2D( GameMain.Instance.GraphicsDevice, width, height, false, SurfaceFormat.Color, DepthFormat.None)) using (SpriteBatch spriteBatch = new SpriteBatch(GameMain.Instance.GraphicsDevice)) { Viewport prevViewport = GameMain.Instance.GraphicsDevice.Viewport; GameMain.Instance.GraphicsDevice.Viewport = new Viewport(0, 0, width, height); GameMain.Instance.GraphicsDevice.SetRenderTarget(rt); GameMain.Instance.GraphicsDevice.Clear(Color.Transparent); DrawBatch(() => Submarine.DrawBack(spriteBatch, editing: false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null))); DrawBatch(() => Submarine.DrawBack(spriteBatch, editing: false, e => (e is not Structure || e.SpriteDepth < 0.9f))); DrawBatch(() => Submarine.DrawDamageable(spriteBatch, null, editing: false)); DrawBatch(() => Submarine.DrawFront(spriteBatch, editing: false)); void DrawBatch(Action drawAction) { spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, null, null, null, transform); drawAction.Invoke(); spriteBatch.End(); } GameMain.Instance.GraphicsDevice.SetRenderTarget(null); GameMain.Instance.GraphicsDevice.Viewport = prevViewport; using (FileStream fs = File.Open("wikiimage.png", System.IO.FileMode.Create)) { rt.SaveAsPng(fs, width, height); } } } } }