From f5dbbf07358edbba95076cab5ca324d68b8726c7 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Wed, 17 Jan 2018 17:01:44 +0200 Subject: [PATCH] Submarine preview window with a preview image & some extra information of the subs --- .../BarotraumaClient/Source/GameMain.cs | 11 +- .../Source/Map/Levels/LevelRenderer.cs | 32 ++-- .../BarotraumaClient/Source/Map/Submarine.cs | 43 +++++- .../Source/Screens/CampaignSetupUI.cs | 11 +- .../Source/Screens/MainMenuScreen.cs | 2 - .../Source/Screens/NetLobbyScreen.cs | 14 +- .../Source/Screens/SubEditorScreen.cs | 142 +++++++++++++++++- .../Source/Utils/TextureLoader.cs | 17 ++- Barotrauma/BarotraumaShared/Content/Texts.xml | 12 ++ .../BarotraumaShared/Content/UI/style.xml | 21 ++- .../BarotraumaShared/Source/Map/Submarine.cs | 92 +++++++++--- 11 files changed, 338 insertions(+), 59 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs index 82405f913..2fd6cbcce 100644 --- a/Barotrauma/BarotraumaClient/Source/GameMain.cs +++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs @@ -20,7 +20,7 @@ namespace Barotrauma public static FrameCounter FrameCounter; public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version; - + public static GameScreen GameScreen; public static MainMenuScreen MainMenuScreen; public static LobbyScreen LobbyScreen; @@ -60,6 +60,8 @@ namespace Barotrauma private static SpriteBatch spriteBatch; + private Viewport defaultViewport; + public static GameMain Instance { get; @@ -169,6 +171,13 @@ namespace Barotrauma GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight; GraphicsDeviceManager.ApplyChanges(); + + defaultViewport = GraphicsDevice.Viewport; + } + + public void ResetViewPort() + { + GraphicsDevice.Viewport = defaultViewport; } /// diff --git a/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelRenderer.cs b/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelRenderer.cs index 1db03e9cd..2c3891e36 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelRenderer.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelRenderer.cs @@ -19,20 +19,32 @@ namespace Barotrauma private Level level; private VertexBuffer wallVertices, bodyVertices; - - //public VertexPositionTexture[] WallVertices; - //public VertexPositionColor[] BodyVertices; - + + public static Sprite Background + { + get + { + if (background == null) background = new Sprite("Content/Map/background2.png", Vector2.Zero); + return background; + } + } + + public static Sprite BackgroundTop + { + get + { + if (backgroundTop == null) backgroundTop = new Sprite("Content/Map/background.png", Vector2.Zero); + return backgroundTop; + } + } + public LevelRenderer(Level level) { if (shaftTexture == null) shaftTexture = TextureLoader.FromFile("Content/Map/iceWall.png"); - if (background==null) - { - background = new Sprite("Content/Map/background2.png", Vector2.Zero); - backgroundTop = new Sprite("Content/Map/background.png", Vector2.Zero); - dustParticles = new Sprite("Content/Map/dustparticles.png", Vector2.Zero); - } + if (background == null) background = new Sprite("Content/Map/background2.png", Vector2.Zero); + if (backgroundTop == null) backgroundTop = new Sprite("Content/Map/background.png", Vector2.Zero); + if (dustParticles == null) dustParticles = new Sprite("Content/Map/dustparticles.png", Vector2.Zero); if (wallEdgeEffect == null) { diff --git a/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs b/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs index 24f89c20f..ca2119dcb 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Submarine.cs @@ -4,13 +4,15 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Xml.Linq; namespace Barotrauma { partial class Submarine : Entity, IServerSerializable { + public Sprite PreviewImage; + public static void Draw(SpriteBatch spriteBatch, bool editing = false) { var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList; @@ -104,7 +106,7 @@ namespace Barotrauma } } - public static bool SaveCurrent(string filePath) + public static bool SaveCurrent(string filePath, MemoryStream previewImage = null) { if (MainSub == null) { @@ -112,7 +114,42 @@ namespace Barotrauma } MainSub.filePath = filePath; - return MainSub.SaveAs(filePath); + return MainSub.SaveAs(filePath, previewImage); + } + + public void CreatePreviewWindow(GUIComponent frame) + { + new GUITextBlock(new Rectangle(0, 0, 0, 20), Name, "", Alignment.TopCenter, Alignment.TopCenter, frame, true, GUI.LargeFont); + + if (PreviewImage == null) + { + var txtBlock = new GUITextBlock(new Rectangle(-10, 60, 256, 128), TextManager.Get("SubPreviewImageNotFound"), Color.Black * 0.5f, null, Alignment.Center, "", frame, true); + txtBlock.OutlineColor = txtBlock.TextColor; + } + else + { + new GUIImage(new Rectangle(-10, 60, 256, 128), PreviewImage, Alignment.TopLeft, frame); + } + + Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio; + string dimensionsStr = realWorldDimensions == Vector2.Zero ? + TextManager.Get("Unknown") : + TextManager.Get("DimensionsFormat").Replace("[width]", ((int)(realWorldDimensions.X)).ToString()).Replace("[height]", ((int)(realWorldDimensions.Y)).ToString()); + + new GUITextBlock(new Rectangle(256, 60, 100, 20), + TextManager.Get("Dimensions") + ": " + dimensionsStr, + "", frame, GUI.SmallFont); + + new GUITextBlock(new Rectangle(256, 80, 100, 20), + TextManager.Get("RecommendedCrewSize") + ": " + (RecommendedCrewSizeMax == 0 ? TextManager.Get("Unknown") : RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax), + "", frame, GUI.SmallFont); + + new GUITextBlock(new Rectangle(256, 100, 100, 20), + TextManager.Get("RecommendedCrewExperience") + ": " + (string.IsNullOrEmpty(RecommendedCrewExperience) ? TextManager.Get("unknown") : RecommendedCrewExperience), + "", frame, GUI.SmallFont); + + var descr = new GUITextBlock(new Rectangle(0, 200, 0, 100), Description, "", Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont); + descr.CanBeFocused = false; } public void CheckForErrors() diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 69c865623..c8231743e 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -109,10 +109,19 @@ namespace Barotrauma { textBlock.TextColor = textBlock.TextColor * 0.85f; - var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), TextManager.Get("Shuttle"), "", Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont); + var shuttleText = new GUITextBlock(new Rectangle(-20, 0, 0, 25), TextManager.Get("Shuttle"), "", Alignment.CenterRight, Alignment.CenterRight, textBlock, false, GUI.SmallFont); shuttleText.TextColor = textBlock.TextColor * 0.8f; shuttleText.ToolTip = textBlock.ToolTip; } + + GUIButton infoButton = new GUIButton(new Rectangle(0, 0, 20, 20), "?", Alignment.CenterRight, "", textBlock); + infoButton.UserData = sub; + infoButton.OnClicked += (component, userdata) => + { + var msgBox = new GUIMessageBox("", "", 550, 350); + ((Submarine)userdata).CreatePreviewWindow(msgBox.InnerFrame); + return true; + }; } if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]); } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index 08b6a7791..95c1435de 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -3,8 +3,6 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.IO; -using System.Linq; -using System.Xml.Linq; namespace Barotrauma { diff --git a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs index 8b7334903..5978c4a96 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/NetLobbyScreen.cs @@ -755,8 +755,7 @@ namespace Barotrauma ToolTip = sub.Description, UserData = sub }; - - + var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name && s.MD5Hash.Hash == sub.MD5Hash.Hash); if (matchingSub == null) matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == sub.Name); @@ -776,11 +775,20 @@ namespace Barotrauma { subTextBlock.TextColor = new Color(subTextBlock.TextColor, sub.HasTag(SubmarineTag.Shuttle) ? 1.0f : 0.6f); } + + GUIButton infoButton = new GUIButton(new Rectangle(0, 0, 20, 20), "?", Alignment.CenterRight, "", subTextBlock); + infoButton.UserData = sub; + infoButton.OnClicked += (component, userdata) => + { + var msgBox = new GUIMessageBox("", "", 550, 350); + ((Submarine)userdata).CreatePreviewWindow(msgBox.InnerFrame); + return true; + }; } if (sub.HasTag(SubmarineTag.Shuttle)) { - var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), TextManager.Get("Shuttle"), "", Alignment.Left, Alignment.CenterY | Alignment.Right, subTextBlock, false, GUI.SmallFont); + var shuttleText = new GUITextBlock(new Rectangle(-20, 0, 0, 25), TextManager.Get("Shuttle"), "", Alignment.CenterRight, Alignment.CenterRight, subTextBlock, false, GUI.SmallFont); shuttleText.TextColor = subTextBlock.TextColor * 0.8f; shuttleText.ToolTip = subTextBlock.ToolTip; } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 84f067902..e89c7d5c8 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -13,6 +13,13 @@ namespace Barotrauma { class SubEditorScreen : Screen { + private static string[] crewExperienceLevels = new string[] + { + TextManager.Get("CrewExperienceLow"), + TextManager.Get("CrewExperienceMid"), + TextManager.Get("CrewExperienceHigh") + }; + private Camera cam; private BlurEffect lightBlur; @@ -406,7 +413,6 @@ namespace Barotrauma } string savePath = nameBox.Text + ".sub"; - if (Submarine.MainSub != null) { savePath = Path.Combine(Path.GetDirectoryName(Submarine.MainSub.FilePath), savePath); @@ -416,9 +422,12 @@ namespace Barotrauma savePath = Path.Combine(Submarine.SavePath, savePath); } - Submarine.SaveCurrent(savePath); + MemoryStream imgStream = new MemoryStream(); + CreateImage(256, 128, imgStream); + + Submarine.SaveCurrent(savePath, imgStream); Submarine.MainSub.CheckForErrors(); - + GUI.AddMessage(TextManager.Get("SubSavedNotification").Replace("[filepath]", Submarine.MainSub.FilePath), Color.Green, 3.0f); Submarine.RefreshSavedSubs(); @@ -467,7 +476,7 @@ namespace Barotrauma descriptionBox.Text = Submarine.MainSub == null ? "" : Submarine.MainSub.Description; descriptionBox.OnTextChanged = ChangeSubDescription; - y += descriptionBox.Rect.Height + 15; + y += descriptionBox.Rect.Height; new GUITextBlock(new Rectangle(0, y, 150, 20), TextManager.Get("SaveSubDialogSettings"), "", saveFrame); y += 20; @@ -480,7 +489,7 @@ namespace Barotrauma string tagStr = attributes.Length > 0 ? attributes[0].Description : ""; - var tagTickBox = new GUITickBox(new Rectangle(tagX, y+ tagY, 20, 20), tagStr, Alignment.TopLeft, saveFrame); + var tagTickBox = new GUITickBox(new Rectangle(tagX, y + tagY, 20, 20), tagStr, Alignment.TopLeft, saveFrame); tagTickBox.Selected = Submarine.MainSub == null ? false : Submarine.MainSub.HasTag(tag); tagTickBox.UserData = tag; @@ -507,7 +516,74 @@ namespace Barotrauma tagX += 200; } } - + + y += tagY; + + new GUITextBlock(new Rectangle(0, y, 100, 20), TextManager.Get("RecommendedCrewSize"), "", Alignment.TopLeft, Alignment.CenterLeft, saveFrame); + + var crewSizeMin = new GUINumberInput(new Rectangle(230, y, 50, 20), "", GUINumberInput.NumberType.Int, saveFrame); + crewSizeMin.MinValueInt = 1; + crewSizeMin.MaxValueInt = 128; + + + new GUITextBlock(new Rectangle(285, y, 10, 20), "-", "", Alignment.TopLeft, Alignment.Center, saveFrame); + + var crewSizeMax = new GUINumberInput(new Rectangle(300, y, 50, 20), "", GUINumberInput.NumberType.Int, saveFrame); + crewSizeMax.MinValueInt = 1; + crewSizeMax.MaxValueInt = 128; + + crewSizeMin.OnValueChanged += (numberInput) => + { + crewSizeMax.IntValue = Math.Max(crewSizeMax.IntValue, numberInput.IntValue); + Submarine.MainSub.RecommendedCrewSizeMin = crewSizeMin.IntValue; + Submarine.MainSub.RecommendedCrewSizeMax = crewSizeMax.IntValue; + }; + + crewSizeMax.OnValueChanged += (numberInput) => + { + crewSizeMin.IntValue = Math.Min(crewSizeMin.IntValue, numberInput.IntValue); + Submarine.MainSub.RecommendedCrewSizeMin = crewSizeMin.IntValue; + Submarine.MainSub.RecommendedCrewSizeMax = crewSizeMax.IntValue; + }; + + y += 20; + + new GUITextBlock(new Rectangle(0, y, 100, 20), TextManager.Get("RecommendedCrewExperience"), "", Alignment.TopLeft, Alignment.CenterLeft, saveFrame); + + var toggleExpLeft = new GUIButton(new Rectangle(230, y, 20, 20), "<", "", saveFrame); + var toggleExpRight = new GUIButton(new Rectangle(350, y, 20, 20), ">", "", saveFrame); + var experienceText = new GUITextBlock(new Rectangle(250, y, 100, 20), crewExperienceLevels[0], "", Alignment.TopLeft, Alignment.Center, saveFrame); + + toggleExpLeft.OnClicked += (btn, userData) => + { + int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text); + currentIndex--; + if (currentIndex < 0) currentIndex = crewExperienceLevels.Length - 1; + experienceText.Text = crewExperienceLevels[currentIndex]; + Submarine.MainSub.RecommendedCrewExperience = experienceText.Text; + return true; + }; + + toggleExpRight.OnClicked += (btn, userData) => + { + int currentIndex = Array.IndexOf(crewExperienceLevels, experienceText.Text); + currentIndex++; + if (currentIndex >= crewExperienceLevels.Length) currentIndex = 0; + experienceText.Text = crewExperienceLevels[currentIndex]; + Submarine.MainSub.RecommendedCrewExperience = experienceText.Text; + return true; + }; + + if (Submarine.MainSub != null) + { + int min = Submarine.MainSub.RecommendedCrewSizeMin; + int max = Submarine.MainSub.RecommendedCrewSizeMax; + crewSizeMin.IntValue = min; + crewSizeMax.IntValue = max; + experienceText.Text = string.IsNullOrEmpty(Submarine.MainSub.RecommendedCrewExperience) ? + crewExperienceLevels[0] : Submarine.MainSub.RecommendedCrewExperience; + } + var saveButton = new GUIButton(new Rectangle(-90, 0, 80, 20), TextManager.Get("SaveSubButton"), Alignment.Right | Alignment.Bottom, "", saveFrame); saveButton.OnClicked = SaveSub; @@ -1273,6 +1349,11 @@ namespace Barotrauma /// public override void Update(double deltaTime) { + if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.T)) + { + SaveScreenShot(256, 128, "screenshottest.png"); + } + if (tutorial != null) tutorial.Update((float)deltaTime); hullVolumeFrame.Visible = MapEntity.SelectedList.Any(s => s is Hull); @@ -1482,5 +1563,54 @@ namespace Barotrauma spriteBatch.End(); } + + private void CreateImage(int width, int height, Stream stream) + { + MapEntity.SelectedList.Clear(); + + RenderTarget2D rt = new RenderTarget2D( + GameMain.Instance.GraphicsDevice, + width, height, false, SurfaceFormat.Color, DepthFormat.None); + + var prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle; + + Rectangle subDimensions = Submarine.MainSub.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; + + GameMain.Instance.GraphicsDevice.SetRenderTarget(rt); + SpriteBatch spriteBatch = new SpriteBatch(GameMain.Instance.GraphicsDevice); + + spriteBatch.Begin(); + LevelRenderer.BackgroundTop.Draw(spriteBatch, Vector2.Zero, new Color(0.025f, 0.075f, 0.131f, 1.0f)); + spriteBatch.End(); + + spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, transform); + Submarine.Draw(spriteBatch, false); + Submarine.DrawFront(spriteBatch); + Submarine.DrawDamageable(spriteBatch, null); + spriteBatch.End(); + + GameMain.Instance.GraphicsDevice.SetRenderTarget(null); + rt.SaveAsPng(stream, width, height); + rt.Dispose(); + + //for some reason setting the rendertarget changes the size of the viewport + //but it doesn't change back to default when setting it back to null + GameMain.Instance.ResetViewPort(); + } + + public void SaveScreenShot(int width, int height, string filePath) + { + Stream stream = File.OpenWrite(filePath); + CreateImage(width, height, stream); + stream.Dispose(); + } } } diff --git a/Barotrauma/BarotraumaClient/Source/Utils/TextureLoader.cs b/Barotrauma/BarotraumaClient/Source/Utils/TextureLoader.cs index 706c11878..e77eceafe 100644 --- a/Barotrauma/BarotraumaClient/Source/Utils/TextureLoader.cs +++ b/Barotrauma/BarotraumaClient/Source/Utils/TextureLoader.cs @@ -43,7 +43,6 @@ namespace Barotrauma { try { - using (Stream fileStream = File.OpenRead(path)) { var texture = Texture2D.FromStream(_graphicsDevice, fileStream); @@ -54,10 +53,24 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Loading texture \""+path+"\" failed!", e); + DebugConsole.ThrowError("Loading texture \"" + path + "\" failed!", e); return null; } + } + public static Texture2D FromStream(Stream fileStream, bool preMultiplyAlpha = true) + { + try + { + var texture = Texture2D.FromStream(_graphicsDevice, fileStream); + texture = PreMultiplyAlpha(texture); + return texture; + } + catch (Exception e) + { + DebugConsole.ThrowError("Loading texture from stream failed!", e); + return null; + } } private static Texture2D PreMultiplyAlpha(Texture2D texture) diff --git a/Barotrauma/BarotraumaShared/Content/Texts.xml b/Barotrauma/BarotraumaShared/Content/Texts.xml index d3d9c85f3..cba733152 100644 --- a/Barotrauma/BarotraumaShared/Content/Texts.xml +++ b/Barotrauma/BarotraumaShared/Content/Texts.xml @@ -91,6 +91,7 @@ Editing Error Warning + Unknown None Close Cancel @@ -240,6 +241,17 @@ "The submarine does not have spawnpoints for cargo (which are used for determining where to place bought items). To fix this, create a new spawnpoint and change its "spawn type" parameter to "cargo". One or more structures have been placed very far from the submarine. Show the structures? + + + Dimensions + [width]x[height] m + Preview image not found + Recommended crew size + Recommended crew experience + Beginner + Intermediate + Experienced + Waypoint Hold space to link to another waypoint diff --git a/Barotrauma/BarotraumaShared/Content/UI/style.xml b/Barotrauma/BarotraumaShared/Content/UI/style.xml index fcec58d47..fd3227ec3 100644 --- a/Barotrauma/BarotraumaShared/Content/UI/style.xml +++ b/Barotrauma/BarotraumaShared/Content/UI/style.xml @@ -223,17 +223,22 @@ + - + + (); - ID = ushort.MaxValue; base.Remove(); } @@ -474,6 +497,28 @@ namespace Barotrauma return position; } + + public Rectangle CalculateDimensions(bool onlyHulls = true) + { + List entities = onlyHulls ? + Hull.hullList.FindAll(h => h.Submarine == this).Cast().ToList() : + MapEntity.mapEntityList.FindAll(me => me.Submarine == this); + + if (entities.Count == 0) return Rectangle.Empty; + + float minX = entities[0].Rect.X, minY = entities[0].Rect.Y - entities[0].Rect.Height; + float maxX = entities[0].Rect.Right, maxY = entities[0].Rect.Y; + + for (int i = 1; i < entities.Count; i++) + { + minX = Math.Min(minX, entities[i].Rect.X); + minY = Math.Min(minY, entities[i].Rect.Y - entities[i].Rect.Height); + maxX = Math.Max(maxX, entities[i].Rect.Right); + maxY = Math.Max(maxY, entities[i].Rect.Y); + } + + return new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY)); + } public static Rectangle AbsRect(Vector2 pos, Vector2 size) { @@ -871,10 +916,10 @@ namespace Barotrauma { SavedSubmarines.Add(new Submarine(path)); } - - //if (GameMain.NetLobbyScreen!=null) GameMain.NetLobbyScreen.UpdateSubList(Submarine.SavedSubmarines); } + static readonly string TempFolder = Path.Combine("Submarine", "Temp"); + public static XDocument OpenFile(string file) { XDocument doc = null; @@ -962,7 +1007,7 @@ namespace Barotrauma Description = submarineElement.GetAttributeString("description", ""); Enum.TryParse(submarineElement.GetAttributeString("tags", ""), out tags); - + //place the sub above the top of the level HiddenSubPosition = HiddenSubStartPosition; if (GameMain.GameSession != null && GameMain.GameSession.Level != null) @@ -1111,27 +1156,23 @@ namespace Barotrauma Submarine sub = new Submarine(path); sub.Load(unloadPrevious); - - //Entity.dictionary.Add(int.MaxValue, sub); - + return sub; } - - - public bool Save() + + public bool SaveAs(string filePath, MemoryStream previewImage = null) { - return SaveAs(filePath); - } - - public bool SaveAs(string filePath) - { - name = System.IO.Path.GetFileNameWithoutExtension(filePath); + name = Path.GetFileNameWithoutExtension(filePath); XDocument doc = new XDocument(new XElement("Submarine")); SaveToXElement(doc.Root); hash = new Md5Hash(doc); doc.Root.Add(new XAttribute("md5hash", hash.Hash)); + if (previewImage != null) + { + doc.Root.Add(new XAttribute("previewimage", Convert.ToBase64String(previewImage.ToArray()))); + } try { @@ -1149,10 +1190,15 @@ namespace Barotrauma public void SaveToXElement(XElement element) { element.Add(new XAttribute("name", name)); - element.Add(new XAttribute("description", Description == null ? "" : Description)); - + element.Add(new XAttribute("description", Description ?? "")); element.Add(new XAttribute("tags", tags.ToString())); + Rectangle dimensions = CalculateDimensions(); + element.Add(new XAttribute("dimensions", XMLExtensions.Vector2ToString(dimensions.Size.ToVector2()))); + element.Add(new XAttribute("recommendedcrewsizemin", RecommendedCrewSizeMin)); + element.Add(new XAttribute("recommendedcrewsizemax", RecommendedCrewSizeMax)); + element.Add(new XAttribute("recommendedcrewexperience", RecommendedCrewExperience ?? "")); + foreach (MapEntity e in MapEntity.mapEntityList) { if (e.MoveWithLevel || e.Submarine != this) continue;