From c64dbed55d8c0cfc814314af2841b6484c5fd87e Mon Sep 17 00:00:00 2001 From: Regalis Date: Sun, 28 Feb 2016 21:08:52 +0200 Subject: [PATCH] Resizing structures/items in editor --- Subsurface/Source/Items/Item.cs | 4 +- Subsurface/Source/Map/Gap.cs | 72 ++++++++--------- Subsurface/Source/Map/Hull.cs | 23 +++++- Subsurface/Source/Map/MapEntity.cs | 124 ++++++++++++++++++++++++++--- Subsurface/Source/Map/Structure.cs | 2 +- Subsurface/Source/Map/WayPoint.cs | 2 +- Subsurface/changelog.txt | 22 +++++ Subsurface_Solution.v12.suo | Bin 875008 -> 850432 bytes 8 files changed, 193 insertions(+), 56 deletions(-) diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index fe5e3c6cf..8d38540e3 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -286,7 +286,7 @@ namespace Barotrauma } public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine) - : base(submarine) + : base(itemPrefab, submarine) { prefab = itemPrefab; @@ -1219,7 +1219,7 @@ namespace Barotrauma element.Add(new XAttribute("name", prefab.Name), new XAttribute("ID", ID)); - if (prefab.ResizeHorizontal || prefab.ResizeVertical) + if (ResizeHorizontal || ResizeVertical) { element.Add(new XAttribute("rect", (int)(rect.X - Submarine.HiddenSubPosition.X) + "," + diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index b89793040..5b24d7b07 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -20,15 +20,15 @@ namespace Barotrauma //private Sound waterSound; //a value between 0.0f-1.0f (0.0 = closed, 1.0f = open) - float open; + private float open; //the force of the water flow which is exerted on physics bodies - Vector2 flowForce; + private Vector2 flowForce; - Hull flowTargetHull; + private Hull flowTargetHull; - float higherSurface; - float lowerSurface; + private float higherSurface; + private float lowerSurface; public float Open @@ -39,11 +39,6 @@ namespace Barotrauma public Door ConnectedDoor; - //public Vector2 FlowForce - //{ - // get { return flowForce*soundVolume; } - //} - public Vector2 LerpedFlowForce { get { return lerpedFlowForce; } @@ -64,6 +59,20 @@ namespace Barotrauma } } + public override Rectangle Rect + { + get + { + return base.Rect; + } + set + { + base.Rect = value; + + FindHulls(); + } + } + public Gap(MapEntityPrefab prefab, Rectangle rectangle) : this (rectangle, Submarine.Loaded) { } @@ -73,7 +82,7 @@ namespace Barotrauma { } public Gap(Rectangle newRect, bool isHorizontal, Submarine submarine) - : base (submarine) + : base (MapEntityPrefab.list.Find(m=> m.Name == "Gap"), submarine) { rect = newRect; linkedTo = new ObservableCollection(); @@ -169,34 +178,21 @@ namespace Barotrauma GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y, rect.Width, rect.Height), clr * 0.5f, true); - if (isHorizontal) + for (int i = 0; i < linkedTo.Count; i++) { - for (int i = 0; i < linkedTo.Count; i++ ) - { - if (linkedTo[i].Rect.Center.X > rect.Center.X) - { - GUI.DrawRectangle(sb, new Rectangle(WorldRect.Right, -WorldRect.Y, 10, rect.Height), Color.Green * 0.3f, true); - } - else - { - GUI.DrawRectangle(sb, new Rectangle(WorldRect.X - 10, -WorldRect.Y, 10, rect.Height), Color.Green * 0.3f, true); - } - } - } - else - { - for (int i = 0; i < linkedTo.Count; i++) - { - if (linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f > rect.Y-rect.Height/2.0f) - { - GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y - 10, rect.Width, 10), Color.Green * 0.3f, true); - } - else - { - GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y + rect.Height, rect.Width, 10), Color.Green * 0.3f, true); - } - } - } + Vector2 dir = isHorizontal ? + new Vector2(Math.Sign(linkedTo[i].Rect.Center.X - rect.Center.X), 0.0f) + : new Vector2(0.0f, Math.Sign((linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f) - (rect.Y - rect.Height / 2.0f))); + + Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2)); + arrowPos += new Vector2(dir.X * (WorldRect.Width / 2 + 10), dir.Y * (WorldRect.Height / 2 + 10)); + + GUI.Arrow.Draw(sb, + arrowPos, + clr * 0.8f, + GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2, + isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f)); + } if (isSelected) { diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index de63e87d8..c65d22791 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -74,6 +74,21 @@ namespace Barotrauma } } + public override Rectangle Rect + { + get + { + return base.Rect; + } + set + { + base.Rect = value; + + Item.UpdateHulls(); + Gap.UpdateHulls(); + } + } + public override bool IsLinkable { get { return true; } @@ -151,13 +166,13 @@ namespace Barotrauma } public Hull(MapEntityPrefab prefab, Rectangle rectangle) - : this (rectangle, Submarine.Loaded) + : this (prefab, rectangle, Submarine.Loaded) { } - public Hull(Rectangle rectangle, Submarine submarine) - : base (submarine) + public Hull(MapEntityPrefab prefab, Rectangle rectangle, Submarine submarine) + : base (prefab, submarine) { rect = rectangle; @@ -691,7 +706,7 @@ namespace Barotrauma int.Parse(element.Attribute("height").Value)); } - Hull h = new Hull(rect, submarine); + Hull h = new Hull(MapEntityPrefab.list.Find(m => m.Name == "Hull"), rect, submarine); h.volume = ToolBox.GetAttributeFloat(element, "pressure", 0.0f); diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index ac310e5bb..12713e97f 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -23,7 +23,9 @@ namespace Barotrauma protected static Vector2 selectionSize = Vector2.Zero; protected static Vector2 startMovingPos = Vector2.Zero; - + + private MapEntityPrefab prefab; + protected List linkedToID; //observable collection because some entities may need to be notified when the collection is modified @@ -66,6 +68,9 @@ namespace Barotrauma //the position and dimensions of the entity protected Rectangle rect; + + private static bool resizing; + private int resizeDirX, resizeDirY; public virtual Rectangle Rect { get { return rect; } @@ -139,12 +144,24 @@ namespace Barotrauma set { isSelected = value; } } + protected bool ResizeHorizontal + { + get { return prefab == null ? false : prefab.ResizeHorizontal; } + } + protected bool ResizeVertical + { + get { return prefab == null ? false : prefab.ResizeVertical; } + } + public virtual string Name { get { return ""; } } - public MapEntity(Submarine submarine) : base(submarine) { } + public MapEntity(MapEntityPrefab prefab, Submarine submarine) : base(submarine) + { + this.prefab = prefab; + } public virtual void Move(Vector2 amount) { @@ -232,6 +249,12 @@ namespace Barotrauma /// public static void UpdateSelecting(Camera cam) { + if (resizing) + { + if (selectedList.Count == 0) resizing = false; + return; + } + foreach (MapEntity e in mapEntityList) { e.isHighlighted = false; @@ -245,7 +268,7 @@ namespace Barotrauma } if (GUIComponent.MouseOn != null || !PlayerInput.MouseInsideWindow) return; - + if (MapEntityPrefab.Selected != null) { selectionPos = Vector2.Zero; @@ -412,6 +435,11 @@ namespace Barotrauma if (selectedList.Count == 1) { selectedList[0].DrawEditing(spriteBatch, cam); + + if (selectedList[0].ResizeHorizontal || selectedList[0].ResizeVertical) + { + selectedList[0].DrawResizing(spriteBatch, cam); + } } else { @@ -443,6 +471,89 @@ namespace Barotrauma public virtual void DrawEditing(SpriteBatch spriteBatch, Camera cam) {} + private void DrawResizing(SpriteBatch spriteBatch, Camera cam) + { + isHighlighted = true; + + int startX = ResizeHorizontal ? -1 : 0; + int StartY = ResizeVertical ? -1 : 0; + + for (int x = startX; x < 2; x += 2) + { + for (int y = StartY; y < 2; y += 2) + { + + Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f + 5), y * (rect.Height * 0.5f + 5))); + + bool highlighted = Vector2.Distance(PlayerInput.MousePosition, handlePos)<5.0f; + + GUI.DrawRectangle(spriteBatch, handlePos - new Vector2(3.0f, 3.0f), new Vector2(6.0f, 6.0f), Color.White * (highlighted ? 1.0f : 0.6f), true); + + if (highlighted) + { + if (PlayerInput.LeftButtonDown()) + { + selectionPos = Vector2.Zero; + resizeDirX = x; + resizeDirY = y; + resizing = true; + } + } + } + } + + if (resizing) + { + + Vector2 placePosition = new Vector2(rect.X, rect.Y); + Vector2 placeSize = new Vector2(rect.Width, rect.Height); + + Vector2 mousePos = Submarine.MouseToWorldGrid(cam); + + if (resizeDirX >0) + { + mousePos.X = Math.Max(mousePos.X, rect.X + Submarine.GridSize.X); + placeSize.X = mousePos.X - placePosition.X; + } + else if (resizeDirX <0) + { + mousePos.X = Math.Min(mousePos.X, rect.Right - Submarine.GridSize.X); + + placeSize.X = (placePosition.X + placeSize.X)-mousePos.X; + placePosition.X = mousePos.X; + } + if (resizeDirY < 0) + { + mousePos.Y = Math.Min(mousePos.Y, rect.Y - Submarine.GridSize.Y); + placeSize.Y = placePosition.Y-mousePos.Y; + } + else if (resizeDirY > 0) + { + mousePos.Y = Math.Max(mousePos.Y, rect.Y - rect.Height + Submarine.GridSize.X); + + placeSize.Y = mousePos.Y - (rect.Y - rect.Height); + placePosition.Y = mousePos.Y; + } + + if ((int)placePosition.X != rect.X || (int)placePosition.Y != rect.Y || (int)placeSize.X != rect.Width || (int)placeSize.Y != rect.Height) + { + Rect = new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y); + } + + if (!PlayerInput.LeftButtonHeld()) + { + resizing = false; + } + + //if (resizeHorizontal) placeSize.X = position.X - placePosition.X; + //if (resizeVertical) placeSize.Y = placePosition.Y - position.Y; + + //Rectangle newRect = Submarine.AbsRect(placePosition, placeSize); + //newRect.Width = (int)Math.Max(newRect.Width, Submarine.GridSize.X); + //newRect.Height = (int)Math.Max(newRect.Height, Submarine.GridSize.Y); + } + } + public static List FindMapEntities(Vector2 pos) { List foundEntities = new List(); @@ -518,13 +629,6 @@ namespace Barotrauma { mapEntityList[i].OnMapLoaded(); } - - - - //mapEntityList.Sort((x, y) => - //{ - // return x.Name.CompareTo(y.Name); - //}); } diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 4811dc103..541cea00c 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -141,7 +141,7 @@ namespace Barotrauma } public Structure(Rectangle rectangle, StructurePrefab sp, Submarine submarine) - : base(submarine) + : base(sp, submarine) { if (rectangle.Width == 0 || rectangle.Height == 0) return; diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index e84e0548f..13d850e65 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -96,7 +96,7 @@ namespace Barotrauma } public WayPoint(Rectangle newRect, Submarine submarine) - : base (submarine) + : base (null, submarine) { rect = newRect; linkedTo = new ObservableCollection(); diff --git a/Subsurface/changelog.txt b/Subsurface/changelog.txt index d98901abe..d85390608 100644 --- a/Subsurface/changelog.txt +++ b/Subsurface/changelog.txt @@ -1,3 +1,25 @@ +--------------------------------------------------------------------------------------------------------- +v0.3.4.0 +--------------------------------------------------------------------------------------------------------- + +Multiplayer: +- missing submarine files can be downloaded from the server host +- player syncing bugfixes (aiming is visible to other players, smoother movement in water) +- creature syncing bugfixes (less teleporting around) +- fixed the server lobby displaying wrong numbers of votes at the client's side +- fixed the server list displaying 16/16 players as 0/16 +- saving server settings + +Other: +- skyholder artifacts consume oxygen +- thermal artifacts catch fire even if they're not being held +- placed items/structures can be resized in the editor +- items in the inventory can be swapped between slots by dragging them on top of each other +- slower underwater scooters +- fixed pressure building up in enclosed rooms full of water, even if there were no hull breaches +- an indicator which shows the direction of the sub when spectating +- fixed crashing when loading a submarine with no hulls + --------------------------------------------------------------------------------------------------------- v0.3.3.1 --------------------------------------------------------------------------------------------------------- diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 9461ffab388f6ac3c0c30809b8a7ad858e0cbc2c..96beba821636648f5f41c4cb7c05d1e6c016d91f 100644 GIT binary patch delta 13266 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 delta 10892 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