(f0d812055) v0.9.9.0

This commit is contained in:
Joonas Rikkonen
2020-04-23 19:19:37 +03:00
parent b647059b93
commit ac37a3b0e4
391 changed files with 15054 additions and 5420 deletions
@@ -24,7 +24,7 @@ namespace Barotrauma
public override void Draw(SpriteBatch sb, bool editing, bool back = true)
{
if (GameMain.DebugDraw)
if (!GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
{
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height / 2.0f));
GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y) / 10.0f, GUI.Style.Red);
@@ -41,7 +41,7 @@ namespace Barotrauma
}
}
if (!editing || !ShowGaps) return;
if (!editing || !ShowGaps) { return; }
Color clr = (open == 0.0f) ? GUI.Style.Red : Color.Cyan;
if (IsHighlighted) clr = Color.Gold;
@@ -76,32 +76,35 @@ namespace Barotrauma
clr * 0.6f, width: lineWidth);
}
for (int i = 0; i < linkedTo.Count; i++)
if (linkedTo.Count != 2 || linkedTo[0] != linkedTo[1])
{
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), dir.Y * (WorldRect.Height / 2));
float arrowWidth = 32.0f;
float arrowSize = 15.0f;
bool invalidDir = false;
if (dir == Vector2.Zero)
for (int i = 0; i < linkedTo.Count; i++)
{
invalidDir = true;
dir = IsHorizontal ? Vector2.UnitX : Vector2.UnitY;
}
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)));
GUI.Arrow.Draw(sb,
arrowPos, invalidDir ? Color.Red : clr * 0.8f,
GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
IsHorizontal ?
new Vector2(Math.Min(rect.Height, arrowWidth) / GUI.Arrow.size.X, arrowSize / GUI.Arrow.size.Y) :
new Vector2(Math.Min(rect.Width, arrowWidth) / GUI.Arrow.size.X, arrowSize / GUI.Arrow.size.Y),
SpriteEffects.None, depth);
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2), dir.Y * (WorldRect.Height / 2));
float arrowWidth = 32.0f;
float arrowSize = 15.0f;
bool invalidDir = false;
if (dir == Vector2.Zero)
{
invalidDir = true;
dir = IsHorizontal ? Vector2.UnitX : Vector2.UnitY;
}
GUI.Arrow.Draw(sb,
arrowPos, invalidDir ? Color.Red : clr * 0.8f,
GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
IsHorizontal ?
new Vector2(Math.Min(rect.Height, arrowWidth) / GUI.Arrow.size.X, arrowSize / GUI.Arrow.size.Y) :
new Vector2(Math.Min(rect.Width, arrowWidth) / GUI.Arrow.size.X, arrowSize / GUI.Arrow.size.Y),
SpriteEffects.None, depth);
}
}
if (IsSelected)
@@ -246,7 +246,7 @@ namespace Barotrauma
if (!ShowHulls && !GameMain.DebugDraw) return;
if (!editing && !GameMain.DebugDraw) return;
if (!editing && (!GameMain.DebugDraw || Screen.Selected.Cam.Zoom < 0.1f)) return;
Rectangle drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
@@ -269,7 +269,8 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * Math.Min(waterVolume / Volume, 1.0f))), Color.Cyan, true);
if (WaterVolume > Volume)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * (waterVolume - Volume) / MaxCompress)), GUI.Style.Red, true);
float maxExcessWater = Volume * MaxCompress;
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * (waterVolume - Volume) / maxExcessWater)), GUI.Style.Red, true);
}
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, 100), Color.Black);
@@ -450,7 +451,7 @@ namespace Barotrauma
}
//we only create a new quad if this is the first or the last one, of if there's a wave large enough that we need more geometry
if (i == end - 1 || i == start || Math.Abs(prevCorners[1].Y - corners[3].Y) > 1.0f)
if (i == end - 1 || i == start || Math.Abs(prevCorners[1].Y - corners[2].Y) > 0.01f)
{
renderer.vertices[renderer.PositionInBuffer] = new VertexPositionTexture(prevCorners[0], prevUVs[0]);
renderer.vertices[renderer.PositionInBuffer + 1] = new VertexPositionTexture(corners[1], uvCoords[1]);
@@ -33,7 +33,9 @@ namespace Barotrauma
foreach (Pair<MapEntityPrefab, Rectangle> entity in DisplayEntities)
{
Rectangle drawRect = entity.Second;
drawRect.Location += Submarine.MouseToWorldGrid(cam, Submarine.MainSub).ToPoint();
drawRect.Location += placePosition != Vector2.Zero ? placePosition.ToPoint() : Submarine.MouseToWorldGrid(cam, Submarine.MainSub).ToPoint();
entity.First.DrawPlacing(spriteBatch, drawRect, entity.First.Scale);
}
}
@@ -39,7 +39,7 @@ namespace Barotrauma
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue;
if (!subElement.Name.ToString().Equals("sprite", System.StringComparison.OrdinalIgnoreCase)) { continue; }
Sprite = new Sprite(subElement, lazyLoad: true);
break;
@@ -1,7 +1,7 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics.Dynamics;
using System;
using System.Linq;
using System.Collections.Generic;
using FarseerPhysics;
@@ -54,7 +54,7 @@ namespace Barotrauma
if (renderer == null) return;
renderer.Draw(spriteBatch, cam);
if (GameMain.DebugDraw)
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
{
foreach (InterestingPosition pos in positionsOfInterest)
{
@@ -78,6 +78,35 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, ruinArea, Color.DarkSlateBlue, false, 0, 5);
}
foreach (var positions in wreckPositions.Values)
{
for (int i = 0; i < positions.Count; i++)
{
float t = (i + 1) / (float)positions.Count;
float multiplier = MathHelper.Lerp(0, 1, t);
Color color = Color.Red * multiplier;
var pos = positions[i];
pos.Y = -pos.Y;
var size = new Vector2(100);
GUI.DrawRectangle(spriteBatch, pos - size / 2, size, color, thickness: 10);
if (i < positions.Count - 1)
{
var nextPos = positions[i + 1];
nextPos.Y = -nextPos.Y;
GUI.DrawLine(spriteBatch, pos, nextPos, color, width: 10);
}
}
}
foreach (var rects in blockedRects.Values)
{
foreach (var rect in rects)
{
Rectangle newRect = rect;
newRect.Y = -newRect.Y;
GUI.DrawRectangle(spriteBatch, newRect, Color.Red, thickness: 5);
}
}
}
}
@@ -126,7 +126,7 @@ namespace Barotrauma
int j = 0;
foreach (XElement subElement in Prefab.Config.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "deformablesprite") continue;
if (!subElement.Name.ToString().Equals("deformablesprite", StringComparison.OrdinalIgnoreCase)) { continue; }
foreach (XElement animationElement in subElement.Elements())
{
var newDeformation = SpriteDeformation.Load(animationElement, Prefab.Name);
@@ -161,7 +161,7 @@ namespace Barotrauma
bool elementFound = false;
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() == "overridecommonness"
if (subElement.Name.ToString().Equals("overridecommonness", System.StringComparison.OrdinalIgnoreCase)
&& subElement.GetAttributeString("leveltype", "") == overrideCommonness.Key)
{
subElement.Attribute("commonness").Value = overrideCommonness.Value.ToString("G", CultureInfo.InvariantCulture);
@@ -228,7 +228,7 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, Camera cam)
{
if (GameMain.DebugDraw && cam.Zoom > 0.05f)
if (GameMain.DebugDraw && cam.Zoom > 0.1f)
{
var cells = level.GetCells(cam.WorldViewCenter, 2);
foreach (VoronoiCell cell in cells)
@@ -91,11 +91,11 @@ namespace Barotrauma
public void RenderWater(SpriteBatch spriteBatch, RenderTarget2D texture, Camera cam)
{
spriteBatch.GraphicsDevice.BlendState = BlendState.NonPremultiplied;
WaterEffect.Parameters["xTexture"].SetValue(texture);
Vector2 distortionStrength = cam == null ? DistortionStrength : DistortionStrength * cam.Zoom;
WaterEffect.Parameters["xWaveWidth"].SetValue(DistortionStrength.X);
WaterEffect.Parameters["xWaveHeight"].SetValue(DistortionStrength.Y);
WaterEffect.Parameters["xWaveWidth"].SetValue(distortionStrength.X);
WaterEffect.Parameters["xWaveHeight"].SetValue(distortionStrength.Y);
if (BlurAmount > 0.0f)
{
WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShaderBlurred"];
@@ -111,6 +111,9 @@ namespace Barotrauma
offset += (cam.Position - new Vector2(cam.WorldView.Width / 2.0f, -cam.WorldView.Height / 2.0f));
offset.Y += cam.WorldView.Height;
offset.X += cam.WorldView.Width;
#if LINUX || OSX
offset.X += cam.WorldView.Width;
#endif
offset *= DistortionScale;
}
offset.Y = -offset.Y;
@@ -176,6 +179,9 @@ namespace Barotrauma
spriteBatch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, subVerts.Value, 0, PositionInIndoorsBuffer[subVerts.Key] / 3);
}
WaterEffect.Parameters["xTexture"].SetValue((Texture2D)null);
WaterEffect.CurrentTechnique.Passes[0].Apply();
}
public void ScrollWater(Vector2 vel, float deltaTime)
@@ -195,7 +201,10 @@ namespace Barotrauma
basicEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
graphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, PositionInBuffer / 3);
graphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, PositionInBuffer / 3);
basicEffect.Texture = null;
basicEffect.CurrentTechnique.Passes[0].Apply();
}
public void ResetBuffers()
@@ -229,7 +229,16 @@ namespace Barotrauma.Lights
light.Position = light.ParentBody.DrawPosition;
if (light.ParentSub != null) { light.Position -= light.ParentSub.DrawPosition; }
}
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.LightSourceParams.TextureRange, viewRect)) { continue; }
float range = light.LightSourceParams.TextureRange;
if (light.LightSprite != null)
{
float spriteRange = Math.Max(
light.LightSprite.size.X * light.SpriteScale.X * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.X - 0.5f)),
light.LightSprite.size.Y * light.SpriteScale.Y * (0.5f + Math.Abs(light.LightSprite.RelativeOrigin.Y - 0.5f)));
range = Math.Max(spriteRange, range);
}
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, range, viewRect)) { continue; }
activeLights.Add(light);
}
@@ -977,7 +977,7 @@ namespace Barotrauma.Lights
origin, -Rotation, SpriteScale, LightSpriteEffect);
}
if (GameMain.DebugDraw)
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
{
Vector2 drawPos = position;
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
@@ -13,11 +13,28 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!editing || wallVertices == null) { return; }
Draw(spriteBatch, Position);
Color color = IsHighlighted ? GUI.Style.Orange : GUI.Style.Green;
if (!Item.ShowLinks) { return; }
foreach (MapEntity e in linkedTo)
{
bool isLinkAllowed = e is Item item && item.HasTag("dock");
GUI.DrawLine(spriteBatch,
new Vector2(WorldPosition.X, -WorldPosition.Y),
new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
isLinkAllowed ? GUI.Style.Green * 0.5f : GUI.Style.Red * 0.5f, width: 3);
}
}
public void Draw(SpriteBatch spriteBatch, Vector2 drawPos, float alpha = 1.0f)
{
Color color = (IsHighlighted) ? GUI.Style.Orange : GUI.Style.Green;
if (IsSelected) { color = GUI.Style.Red; }
Vector2 pos = Position;
Vector2 pos = drawPos;
for (int i = 0; i < wallVertices.Count; i++)
{
@@ -28,26 +45,14 @@ namespace Barotrauma
endPos.Y = -endPos.Y;
GUI.DrawLine(spriteBatch,
startPos,
endPos,
color, 0.0f, 5);
startPos,
endPos,
color * alpha, 0.0f, 5);
}
pos.Y = -pos.Y;
GUI.DrawLine(spriteBatch, pos + Vector2.UnitY * 50.0f, pos - Vector2.UnitY * 50.0f, color, 0.0f, 5);
GUI.DrawLine(spriteBatch, pos + Vector2.UnitX * 50.0f, pos - Vector2.UnitX * 50.0f, color, 0.0f, 5);
if (!Item.ShowLinks) { return; }
foreach (MapEntity e in linkedTo)
{
bool isLinkAllowed = e is Item item && item.HasTag("dock");
GUI.DrawLine(spriteBatch,
new Vector2(WorldPosition.X, -WorldPosition.Y),
new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
isLinkAllowed ? GUI.Style.Green * 0.5f : GUI.Style.Red * 0.5f, width: 3);
}
GUI.DrawLine(spriteBatch, pos + Vector2.UnitY * 50.0f, pos - Vector2.UnitY * 50.0f, color * alpha, 0.0f, 5);
GUI.DrawLine(spriteBatch, pos + Vector2.UnitX * 50.0f, pos - Vector2.UnitX * 50.0f, color * alpha, 0.0f, 5);
}
public override void UpdateEditing(Camera cam)
@@ -100,10 +105,9 @@ namespace Barotrauma
}
var pathContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true);
var pathBox = new GUITextBox(new RectTransform(new Vector2(0.75f, 1.0f), pathContainer.RectTransform), filePath, font: GUI.SmallFont);
var reloadButton = new GUIButton(new RectTransform(new Vector2(0.25f / pathBox.RectTransform.RelativeSize.X, 1.0f), pathBox.RectTransform, Anchor.CenterRight, Pivot.CenterLeft),
TextManager.Get("ReloadLinkedSub"), style: "GUIButtonSmall")
TextManager.Get("ReloadLinkedSub"), style: "GUIButtonSmall")
{
OnClicked = Reload,
UserData = pathBox,
@@ -131,8 +135,9 @@ namespace Barotrauma
return false;
}
XDocument doc = Submarine.OpenFile(pathBox.Text);
XDocument doc = SubmarineInfo.OpenFile(pathBox.Text);
if (doc == null || doc.Root == null) return false;
doc.Root.SetAttributeValue("filepath", pathBox.Text);
pathBox.Flash(GUI.Style.Green);
@@ -16,8 +16,15 @@ namespace Barotrauma
private static Vector2 startMovingPos = Vector2.Zero;
private static float keyDelay;
public static Vector2 StartMovingPos => startMovingPos;
// Quick undo/redo for size and movement only. TODO: Remove if we do a more general implementation.
private Memento<Rectangle> rectMemento;
public event Action<Rectangle> Resized;
private static bool resizing;
private int resizeDirX, resizeDirY;
@@ -127,7 +134,7 @@ namespace Barotrauma
if (highlightedListBox == null ||
(GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn)))
{
UpdateHighlightedListBox(null);
UpdateHighlightedListBox(null, false);
return;
}
}
@@ -142,11 +149,14 @@ namespace Barotrauma
{
if (PlayerInput.KeyDown(Keys.Delete))
{
selectedList.ForEach(e => e.Remove());
selectedList.ForEach(e =>
{
e.Remove();
});
selectedList.Clear();
}
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
if (PlayerInput.IsCtrlDown())
{
if (PlayerInput.KeyHit(Keys.C))
{
@@ -239,32 +249,7 @@ namespace Barotrauma
}
}
if (PlayerInput.MouseSpeed.LengthSquared() > 10)
{
highlightTimer = 0.0f;
}
else
{
bool mouseNearHighlightBox = false;
if (highlightedListBox != null)
{
Rectangle expandedRect = highlightedListBox.Rect;
expandedRect.Inflate(20, 20);
mouseNearHighlightBox = expandedRect.Contains(PlayerInput.MousePosition);
if (!mouseNearHighlightBox) highlightedListBox = null;
}
highlightTimer += (float)Timing.Step;
if (highlightTimer > 1.0f)
{
if (!mouseNearHighlightBox)
{
UpdateHighlightedListBox(highlightedEntities);
highlightTimer = 0.0f;
}
}
}
UpdateHighlighting(highlightedEntities);
}
if (highLightedEntity != null) highLightedEntity.isHighlighted = true;
@@ -272,35 +257,65 @@ namespace Barotrauma
if (GUI.KeyboardDispatcher.Subscriber == null)
{
int up = PlayerInput.KeyDown(Keys.Up) ? 1 : 0,
down = PlayerInput.KeyDown(Keys.Down) ? -1 : 0,
left = PlayerInput.KeyDown(Keys.Left) ? -1 : 0,
right = PlayerInput.KeyDown(Keys.Right) ? 1 : 0;
int xKeysDown = (left + right);
int yKeysDown = (up + down);
if (xKeysDown != 0 || yKeysDown != 0) { keyDelay += (float) Timing.Step; } else { keyDelay = 0; }
Vector2 nudgeAmount = Vector2.Zero;
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (keyDelay >= 0.5f)
{
nudgeAmount.Y = yKeysDown;
nudgeAmount.X = xKeysDown;
}
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (PlayerInput.KeyHit(Keys.Down)) nudgeAmount.Y = -1f;
if (PlayerInput.KeyHit(Keys.Left)) nudgeAmount.X = -1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
if (nudgeAmount != Vector2.Zero)
{
foreach (MapEntity entityToNudge in selectedList)
{
entityToNudge.Move(nudgeAmount);
}
foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudgeAmount); }
}
}
else
{
keyDelay = 0;
}
bool isShiftDown = PlayerInput.IsShiftDown();
//started moving selected entities
if (startMovingPos != Vector2.Zero)
{
Item targetContainer = GetPotentialContainer(position, selectedList);
if (targetContainer != null) { targetContainer.IsHighlighted = true; }
if (PlayerInput.PrimaryMouseButtonReleased())
{
//mouse released -> move the entities to the new position of the mouse
Vector2 moveAmount = position - startMovingPos;
moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X;
moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y;
if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y)
if (!isShiftDown)
{
moveAmount = Submarine.VectorToWorldGrid(moveAmount);
moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X;
moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y;
}
if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y || isShiftDown)
{
if (!isShiftDown) { moveAmount = Submarine.VectorToWorldGrid(moveAmount); }
//clone
if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl))
if (PlayerInput.IsCtrlDown())
{
var clones = Clone(selectedList);
selectedList = clones;
@@ -308,6 +323,7 @@ namespace Barotrauma
}
else // move
{
List<MapEntity> deposited = new List<MapEntity>();
foreach (MapEntity e in selectedList)
{
if (e.rectMemento == null)
@@ -316,8 +332,23 @@ namespace Barotrauma
e.rectMemento.Store(e.Rect);
}
e.Move(moveAmount);
if (isShiftDown && e is Item item && targetContainer != null)
{
if (targetContainer.OwnInventory.TryPutItem(item, Character.Controlled))
{
GUI.PlayUISound(GUISoundType.DropItem);
deposited.Add(item);
}
else
{
GUI.PlayUISound(GUISoundType.PickItemFail);
}
}
e.rectMemento.Store(e.Rect);
}
deposited.ForEach(entity => { selectedList.Remove(entity); });
}
}
startMovingPos = Vector2.Zero;
@@ -352,8 +383,7 @@ namespace Barotrauma
if (PlayerInput.PrimaryMouseButtonReleased())
{
if (PlayerInput.KeyDown(Keys.LeftControl) ||
PlayerInput.KeyDown(Keys.RightControl))
if (PlayerInput.IsCtrlDown())
{
foreach (MapEntity e in newSelection)
{
@@ -436,7 +466,84 @@ namespace Barotrauma
}
}
private static void UpdateHighlightedListBox(List<MapEntity> highlightedEntities)
public static Item GetPotentialContainer(Vector2 position, List<MapEntity> entities = null)
{
Item targetContainer = null;
bool isShiftDown = PlayerInput.IsShiftDown();
if (!isShiftDown) return null;
foreach (MapEntity e in mapEntityList)
{
if (!e.SelectableInEditor ||!(e is Item potentialContainer)) { continue; }
if (e.IsMouseOn(position))
{
if (entities == null)
{
if (potentialContainer.OwnInventory != null && potentialContainer.ParentInventory == null && !potentialContainer.OwnInventory.IsFull())
{
targetContainer = potentialContainer;
break;
}
}
else
{
foreach (MapEntity selectedEntity in entities)
{
if (!(selectedEntity is Item selectedItem)) { continue; }
if (potentialContainer.OwnInventory != null && potentialContainer.ParentInventory == null && potentialContainer != selectedItem &&
potentialContainer.OwnInventory.CanBePut(selectedItem))
{
targetContainer = potentialContainer;
break;
}
}
}
}
if (targetContainer != null) { break; }
}
return targetContainer;
}
/// <summary>
/// Updates the logic that runs the highlight box when the mouse is sitting still.
/// </summary>
/// <see cref="UpdateHighlightedListBox"/>
/// <param name="highlightedEntities"></param>
/// <param name="wiringMode">true to give items tooltip showing their connection</param>
public static void UpdateHighlighting(List<MapEntity> highlightedEntities, bool wiringMode = false)
{
if (PlayerInput.MouseSpeed.LengthSquared() > 10)
{
highlightTimer = 0.0f;
}
else
{
bool mouseNearHighlightBox = false;
if (highlightedListBox != null)
{
Rectangle expandedRect = highlightedListBox.Rect;
expandedRect.Inflate(20, 20);
mouseNearHighlightBox = expandedRect.Contains(PlayerInput.MousePosition);
if (!mouseNearHighlightBox) highlightedListBox = null;
}
highlightTimer += (float)Timing.Step;
if (highlightTimer > 1.0f)
{
if (!mouseNearHighlightBox)
{
UpdateHighlightedListBox(highlightedEntities, wiringMode);
highlightTimer = 0.0f;
}
}
}
}
private static void UpdateHighlightedListBox(List<MapEntity> highlightedEntities, bool wiringMode)
{
if (highlightedEntities == null || highlightedEntities.Count < 2)
{
@@ -453,14 +560,37 @@ namespace Barotrauma
highlightedListBox = new GUIListBox(new RectTransform(new Point(180, highlightedEntities.Count * 18 + 5), GUI.Canvas)
{
MaxSize = new Point(int.MaxValue, 256),
ScreenSpaceOffset = PlayerInput.MousePosition.ToPoint() + new Point(15)
}, style: "GUIToolTip");
foreach (MapEntity entity in highlightedEntities)
{
var textBlock = new GUITextBlock(new RectTransform(new Point(highlightedListBox.Content.Rect.Width, 15), highlightedListBox.Content.RectTransform),
ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), font: GUI.SmallFont)
var tooltip = string.Empty;
if (wiringMode && entity is Item item)
{
var wire = item.GetComponent<Wire>();
if (wire?.Connections != null)
{
for (var i = 0; i < wire.Connections.Length; i++)
{
var conn = wire.Connections[i];
if (conn != null)
{
string[] tags = { "[item]", "[pin]" };
string[] values = { conn.Item?.Name, conn.Name };
tooltip += TextManager.GetWithVariables("wirelistformat",tags , values);
}
if (i != wire.Connections.Length - 1) { tooltip += '\n'; }
}
}
}
var textBlock = new GUITextBlock(new RectTransform(new Point(highlightedListBox.Content.Rect.Width, 15), highlightedListBox.Content.RectTransform),
ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), font: GUI.SmallFont)
{
ToolTip = tooltip,
UserData = entity
};
}
@@ -469,8 +599,7 @@ namespace Barotrauma
{
MapEntity entity = obj as MapEntity;
if (PlayerInput.KeyDown(Keys.LeftControl) ||
PlayerInput.KeyDown(Keys.RightControl))
if (PlayerInput.IsCtrlDown() && !wiringMode)
{
if (selectedList.Contains(entity))
{
@@ -480,11 +609,10 @@ namespace Barotrauma
{
AddSelection(entity);
}
return true;
}
else
{
SelectEntity(entity);
}
SelectEntity(entity);
return true;
};
@@ -553,6 +681,10 @@ namespace Barotrauma
{
item.UpdateSpriteStates(deltaTime);
}
else if (me is Structure structure)
{
structure.UpdateSpriteStates(deltaTime);
}
}
}
@@ -570,24 +702,52 @@ namespace Barotrauma
{
Vector2 moveAmount = position - startMovingPos;
moveAmount.Y = -moveAmount.Y;
moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X;
moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y;
bool isShiftDown = PlayerInput.IsShiftDown();
if (!isShiftDown)
{
moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X;
moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y;
}
//started moving the selected entities
if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y)
if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y || isShiftDown)
{
foreach (MapEntity e in selectedList)
{
SpriteEffects spriteEffects = SpriteEffects.None;
if (e is Item item)
switch (e)
{
if (item.FlippedX && item.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
if (item.flippedY && item.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
}
else if (e is Structure structure)
{
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
case Item item:
{
if (item.FlippedX && item.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
if (item.flippedY && item.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
break;
}
case Structure structure:
{
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
break;
}
case WayPoint wayPoint:
{
Vector2 drawPos = e.WorldPosition;
drawPos.Y = -drawPos.Y;
drawPos += moveAmount;
wayPoint.Draw(spriteBatch, drawPos);
continue;
}
case LinkedSubmarine linkedSub:
{
var ma = moveAmount;
ma.Y = -ma.Y;
Vector2 lPos = linkedSub.Position;
lPos += ma;
linkedSub.Draw(spriteBatch, lPos, alpha: 0.5f);
break;
}
}
e.prefab?.DrawPlacing(spriteBatch,
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteEffects);
@@ -643,7 +803,7 @@ namespace Barotrauma
}
}
if ((PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)))
if (PlayerInput.IsCtrlDown())
{
if (PlayerInput.KeyHit(Keys.N))
{
@@ -721,7 +881,10 @@ namespace Barotrauma
CopyEntities(entities);
entities.ForEach(e => e.Remove());
entities.ForEach(e =>
{
e.Remove();
});
entities.Clear();
}
@@ -834,6 +997,7 @@ namespace Barotrauma
resizeDirX = x;
resizeDirY = y;
resizing = true;
startMovingPos = Vector2.Zero;
}
}
}
@@ -851,6 +1015,11 @@ namespace Barotrauma
Vector2 mousePos = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
if (PlayerInput.IsShiftDown())
{
mousePos = cam.ScreenToWorld(PlayerInput.MousePosition);
}
if (resizeDirX > 0)
{
mousePos.X = Math.Max(mousePos.X, rect.X + Submarine.GridSize.X);
@@ -8,6 +8,12 @@ namespace Barotrauma
{
public virtual void UpdatePlacing(Camera cam)
{
if (PlayerInput.SecondaryMouseButtonClicked())
{
selected = null;
return;
}
Vector2 placeSize = Submarine.GridSize;
if (placePosition == Vector2.Zero)
@@ -41,12 +47,6 @@ namespace Barotrauma
newRect.Y = -newRect.Y;
}
if (PlayerInput.SecondaryMouseButtonHeld())
{
placePosition = Vector2.Zero;
selected = null;
}
}
public virtual void DrawPlacing(SpriteBatch spriteBatch, Camera cam)
@@ -18,11 +18,13 @@ namespace Barotrauma
private List<ConvexHull> convexHulls;
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
public override bool SelectableInEditor
{
get
{
return HasBody ? ShowWalls : ShowStructures;;
return HasBody ? ShowWalls : ShowStructures;
}
}
@@ -38,6 +40,14 @@ namespace Barotrauma
{
Prefab.sprite?.EnsureLazyLoaded();
Prefab.BackgroundSprite?.EnsureLazyLoaded();
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
decorativeSprite.Sprite.EnsureLazyLoaded();
spriteAnimState.Add(decorativeSprite, new DecorativeSprite.State());
}
UpdateSpriteStates(0.0f);
}
partial void CreateConvexHull(Vector2 position, Vector2 size, float rotation)
@@ -156,19 +166,19 @@ namespace Barotrauma
{
Rectangle worldRect = WorldRect;
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) return false;
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) return false;
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) { return false; }
return true;
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (prefab.sprite == null) return;
if (prefab.sprite == null) { return; }
if (editing)
{
if (!HasBody && !ShowStructures) return;
if (HasBody && !ShowWalls) return;
if (!HasBody && !ShowStructures) { return; }
if (HasBody && !ShowWalls) { return; }
}
Draw(spriteBatch, editing, back, null);
@@ -188,12 +198,13 @@ namespace Barotrauma
private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null)
{
if (prefab.sprite == null) return;
if (prefab.sprite == null) { return; }
if (editing)
{
if (!HasBody && !ShowStructures) return;
if (HasBody && !ShowWalls) return;
if (!HasBody && !ShowStructures) { return; }
if (HasBody && !ShowWalls) { return; }
}
else if (HiddenInGame) { return; }
Color color = IsHighlighted ? GUI.Style.Orange : spriteColor;
if (IsSelected && editing)
@@ -254,7 +265,7 @@ namespace Barotrauma
spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
new Vector2(rect.Width, rect.Height),
color: color,
color: Prefab.BackgroundSpriteColor,
textureScale: TextureScale * Scale,
startOffset: backGroundOffset,
depth: Math.Max(Prefab.BackgroundSprite.Depth + (ID % 255) * 0.000001f, depth + 0.000001f));
@@ -318,10 +329,20 @@ namespace Barotrauma
depth: depth,
textureScale: TextureScale * Scale);
}
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
rotation, decorativeSprite.Scale * Scale, prefab.sprite.effects,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.sprite.Depth), 0.999f));
}
prefab.sprite.effects = oldEffects;
}
if (GameMain.DebugDraw)
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.5f)
{
if (Bodies != null)
{
@@ -353,12 +374,70 @@ namespace Barotrauma
}
}
public void UpdateSpriteStates(float deltaTime)
{
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
foreach (int spriteGroup in Prefab.DecorativeSpriteGroups.Keys)
{
for (int i = 0; i < Prefab.DecorativeSpriteGroups[spriteGroup].Count; i++)
{
var decorativeSprite = Prefab.DecorativeSpriteGroups[spriteGroup][i];
if (decorativeSprite == null) { continue; }
if (spriteGroup > 0)
{
int activeSpriteIndex = ID % Prefab.DecorativeSpriteGroups[spriteGroup].Count;
if (i != activeSpriteIndex)
{
spriteAnimState[decorativeSprite].IsActive = false;
continue;
}
}
//check if the sprite is active (whether it should be drawn or not)
var spriteState = spriteAnimState[decorativeSprite];
spriteState.IsActive = true;
foreach (PropertyConditional conditional in decorativeSprite.IsActiveConditionals)
{
if (!ConditionalMatches(conditional))
{
spriteState.IsActive = false;
break;
}
}
if (!spriteState.IsActive) { continue; }
//check if the sprite should be animated
bool animate = true;
foreach (PropertyConditional conditional in decorativeSprite.AnimationConditionals)
{
if (!ConditionalMatches(conditional)) { animate = false; break; }
}
if (!animate) { continue; }
spriteState.OffsetState += deltaTime;
spriteState.RotationState += deltaTime;
}
}
}
private bool ConditionalMatches(PropertyConditional conditional)
{
if (!string.IsNullOrEmpty(conditional.TargetItemComponentName))
{
return false;
}
else
{
if (!conditional.Matches(this)) { return false; }
}
return true;
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
byte sectionCount = msg.ReadByte();
if (sectionCount != Sections.Length)
{
string errorMsg = $"Error while reading a network event for the structure \"{Name}\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
DebugConsole.NewMessage(errorMsg, Color.Red);
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
}
@@ -1,13 +1,29 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
namespace Barotrauma
{
partial class StructurePrefab : MapEntityPrefab
{
public Color BackgroundSpriteColor
{
get;
private set;
}
public List<DecorativeSprite> DecorativeSprites = new List<DecorativeSprite>();
public Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
public override void UpdatePlacing(Camera cam)
{
if (PlayerInput.SecondaryMouseButtonClicked())
{
selected = null;
return;
}
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
Vector2 size = ScaledSize;
Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
@@ -40,7 +56,7 @@ namespace Barotrauma
if (PlayerInput.PrimaryMouseButtonReleased())
{
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
var structure = new Structure(newRect, this, Submarine.MainSub)
new Structure(newRect, this, Submarine.MainSub)
{
Submarine = Submarine.MainSub
};
@@ -49,8 +65,6 @@ namespace Barotrauma
return;
}
}
if (PlayerInput.SecondaryMouseButtonHeld()) selected = null;
}
public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam)
@@ -60,9 +74,6 @@ namespace Barotrauma
if (placePosition == Vector2.Zero)
{
if (PlayerInput.PrimaryMouseButtonHeld())
placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
newRect.X = (int)position.X;
newRect.Y = (int)position.Y;
}
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
namespace Barotrauma
{
@@ -35,7 +36,6 @@ namespace Barotrauma
partial class Submarine : Entity, IServerSerializable
{
public Sprite PreviewImage;
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
{
Vector2 position = PlayerInput.MousePosition;
@@ -56,6 +56,8 @@ namespace Barotrauma
private static List<RoundSound> roundSounds = null;
public static RoundSound LoadRoundSound(XElement element, bool stream = false)
{
if (GameMain.SoundManager?.Disabled ?? true) { return null; }
string filename = element.GetAttributeString("file", "");
if (string.IsNullOrEmpty(filename)) filename = element.GetAttributeString("sound", "");
@@ -222,7 +224,7 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5);
if (sub.subBody == null || sub.subBody.PositionBuffer.Count < 2) continue;
if (sub.SubBody == null || sub.subBody.PositionBuffer.Count < 2) continue;
Vector2 prevPos = ConvertUnits.ToDisplayUnits(sub.subBody.PositionBuffer[0].Position);
prevPos.Y = -prevPos.Y;
@@ -245,7 +247,7 @@ namespace Barotrauma
public static Color DamageEffectColor;
private static readonly List<Structure> depthSortedDamageable = new List<Structure>();
public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false)
public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false, Predicate<MapEntity> predicate = null)
{
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList;
@@ -256,6 +258,10 @@ namespace Barotrauma
{
if (e is Structure structure && structure.DrawDamageEffect)
{
if (predicate != null)
{
if (!predicate(e)) continue;
}
float drawDepth = structure.GetDrawDepth();
int i = 0;
while (i < depthSortedDamageable.Count)
@@ -329,125 +335,6 @@ namespace Barotrauma
}
}
public static bool SaveCurrent(string filePath, MemoryStream previewImage = null)
{
if (MainSub == null)
{
MainSub = new Submarine(filePath);
}
MainSub.filePath = filePath;
return MainSub.SaveAs(filePath, previewImage);
}
public void CreatePreviewWindow(GUIComponent parent)
{
var content = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null);
if (PreviewImage == null)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded"));
}
else
{
var submarinePreviewBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), style: null) { Color = Color.Black };
new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), PreviewImage, scaleToFit: true);
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black);
}
var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter))
{
UserData = "descriptionbox",
ScrollBarVisible = true,
Spacing = 5
};
//space
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), descriptionBox.Content.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("submarine.name." + Name, true) ?? Name, font: GUI.LargeFont, wrap: true) { ForceUpperCase = true, CanBeFocused = false };
float leftPanelWidth = 0.6f;
float rightPanelWidth = 0.4f / leftPanelWidth;
ScalableFont font = descriptionBox.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
if (realWorldDimensions != Vector2.Zero)
{
string dimensionsStr = TextManager.GetWithVariables("DimensionsFormat", new string[2] { "[width]", "[height]" }, new string[2] { ((int)realWorldDimensions.X).ToString(), ((int)realWorldDimensions.Y).ToString() });
var dimensionsText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("Dimensions"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), dimensionsText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
dimensionsStr, textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
dimensionsText.RectTransform.MinSize = new Point(0, dimensionsText.Children.First().Rect.Height);
}
if (RecommendedCrewSizeMax > 0)
{
var crewSizeText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewSizeText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax, textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height);
}
if (!string.IsNullOrEmpty(RecommendedCrewExperience))
{
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
}
if (RequiredContentPackages.Any())
{
var contentPackagesText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RequiredContentPackages"), textAlignment: Alignment.TopLeft, font: font)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
string.Join(", ", RequiredContentPackages), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
contentPackagesText.RectTransform.MinSize = new Point(0, contentPackagesText.Children.First().Rect.Height);
}
// show what game version the submarine was created on
if (!IsVanillaSubmarine() && GameVersion != null)
{
var versionText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("serverlistversion"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), versionText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
GameVersion.ToString(), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
}
GUITextBlock.AutoScaleAndNormalize(descriptionBox.Content.Children.Where(c => c is GUITextBlock).Cast<GUITextBlock>());
//space
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null);
if (!string.IsNullOrEmpty(Description))
{
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform),
TextManager.Get("SaveSubDialogDescription", fallBackTag: "WorkshopItemDescription"), font: GUI.Font, wrap: true) { CanBeFocused = false, ForceUpperCase = true };
}
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), Description, font: font, wrap: true)
{
CanBeFocused = false
};
}
public void CreateMiniMap(GUIComponent parent, IEnumerable<Entity> pointsOfInterest = null)
{
Rectangle worldBorders = GetDockedBorders();
@@ -496,21 +383,6 @@ namespace Barotrauma
}
}
public bool IsVanillaSubmarine()
{
var vanilla = GameMain.VanillaContent;
if (vanilla != null)
{
var vanillaSubs = vanilla.GetFilesOfType(ContentType.Submarine);
string pathToCompare = filePath.Replace(@"\", @"/").ToLowerInvariant();
if (vanillaSubs.Any(sub => sub.Replace(@"\", @"/").ToLowerInvariant() == pathToCompare))
{
return true;
}
}
return false;
}
public void CheckForErrors()
{
List<string> errorMsgs = new List<string>();
@@ -531,6 +403,11 @@ namespace Barotrauma
}
}
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Human))
{
errorMsgs.Add(TextManager.Get("NoHumanSpawnpointWarning"));
}
if (!WayPoint.WayPointList.Any(wp => wp.ShouldBeSaved && wp.SpawnType == SpawnType.Path))
{
errorMsgs.Add(TextManager.Get("NoWaypointsWarning"));
@@ -605,7 +482,7 @@ namespace Barotrauma
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Name);
var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Info.Name);
msg.ReadPadBits();
if (posInfo != null)
@@ -0,0 +1,149 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
partial class SubmarineInfo : IDisposable
{
public Sprite PreviewImage;
partial void InitProjectSpecific()
{
string previewImageData = SubmarineElement.GetAttributeString("previewimage", "");
if (!string.IsNullOrEmpty(previewImageData))
{
try
{
using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
{
var texture = TextureLoader.FromStream(mem, path: FilePath);
if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
PreviewImage = new Sprite(texture, null, null);
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.", e);
GameAnalyticsManager.AddErrorEventOnce("Submarine..ctor:PreviewImageLoadingFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.");
PreviewImage = null;
}
}
}
public void CreatePreviewWindow(GUIComponent parent)
{
var content = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null);
if (PreviewImage == null)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded"));
}
else
{
var submarinePreviewBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), style: null) { Color = Color.Black };
new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), PreviewImage, scaleToFit: true);
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black);
}
var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter))
{
UserData = "descriptionbox",
ScrollBarVisible = true,
Spacing = 5
};
//space
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), descriptionBox.Content.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), TextManager.Get("submarine.name." + Name, true) ?? Name, font: GUI.LargeFont, wrap: true) { ForceUpperCase = true, CanBeFocused = false };
float leftPanelWidth = 0.6f;
float rightPanelWidth = 0.4f / leftPanelWidth;
ScalableFont font = descriptionBox.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
if (realWorldDimensions != Vector2.Zero)
{
string dimensionsStr = TextManager.GetWithVariables("DimensionsFormat", new string[2] { "[width]", "[height]" }, new string[2] { ((int)realWorldDimensions.X).ToString(), ((int)realWorldDimensions.Y).ToString() });
var dimensionsText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("Dimensions"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), dimensionsText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
dimensionsStr, textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
dimensionsText.RectTransform.MinSize = new Point(0, dimensionsText.Children.First().Rect.Height);
}
if (RecommendedCrewSizeMax > 0)
{
var crewSizeText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewSizeText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
RecommendedCrewSizeMin + " - " + RecommendedCrewSizeMax, textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height);
}
if (!string.IsNullOrEmpty(RecommendedCrewExperience))
{
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
}
if (RequiredContentPackages.Any())
{
var contentPackagesText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("RequiredContentPackages"), textAlignment: Alignment.TopLeft, font: font)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), contentPackagesText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
string.Join(", ", RequiredContentPackages), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
contentPackagesText.RectTransform.MinSize = new Point(0, contentPackagesText.Children.First().Rect.Height);
}
// show what game version the submarine was created on
if (!IsVanillaSubmarine() && GameVersion != null)
{
var versionText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), descriptionBox.Content.RectTransform),
TextManager.Get("serverlistversion"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), versionText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
GameVersion.ToString(), textAlignment: Alignment.TopLeft, font: font, wrap: true)
{ CanBeFocused = false };
versionText.RectTransform.MinSize = new Point(0, versionText.Children.First().Rect.Height);
}
GUITextBlock.AutoScaleAndNormalize(descriptionBox.Content.Children.Where(c => c is GUITextBlock).Cast<GUITextBlock>());
//space
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), descriptionBox.Content.RectTransform), style: null);
if (!string.IsNullOrEmpty(Description))
{
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform),
TextManager.Get("SaveSubDialogDescription", fallBackTag: "WorkshopItemDescription"), font: GUI.Font, wrap: true)
{ CanBeFocused = false, ForceUpperCase = true };
}
new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionBox.Content.RectTransform), Description, font: font, wrap: true)
{
CanBeFocused = false
};
}
}
}
@@ -1,17 +1,16 @@
using Microsoft.Xna.Framework;
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using Barotrauma.Items.Components;
using System.Linq;
namespace Barotrauma
{
partial class WayPoint : MapEntity
{
private static Texture2D iconTexture;
private const int IconSize = 32;
private static int[] iconIndices = { 3, 0, 1, 2 };
private static Dictionary<SpawnType, Sprite> iconSprites;
private const int WaypointSize = 12, SpawnPointSize = 32;
public override bool IsVisible(Rectangle worldView)
{
@@ -23,58 +22,58 @@ namespace Barotrauma
get { return !IsHidden(); }
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!editing && !GameMain.DebugDraw) { return; }
if (!editing && (!GameMain.DebugDraw || Screen.Selected.Cam.Zoom < 0.1f)) { return; }
if (IsHidden()) { return; }
//Rectangle drawRect =
// Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
Vector2 drawPos = Position;
if (Submarine != null) drawPos += Submarine.DrawPosition;
if (Submarine != null) { drawPos += Submarine.DrawPosition; }
drawPos.Y = -drawPos.Y;
Color clr = currentHull == null ? Color.Blue : Color.White;
Draw(spriteBatch, drawPos);
}
public void Draw(SpriteBatch spriteBatch, Vector2 drawPos)
{
Color clr = currentHull == null ? Color.CadetBlue : GUI.Style.Green;
if (spawnType != SpawnType.Path) { clr = Color.Gray; }
if (isObstructed)
{
clr = Color.Black;
}
if (IsSelected) clr = GUI.Style.Red;
if (IsHighlighted) clr = Color.DarkRed;
if (IsHighlighted || IsHighlighted) { clr = Color.Lerp(clr, Color.White, 0.8f); }
int iconX = iconIndices[(int)spawnType] * IconSize % iconTexture.Width;
int iconY = (int)(Math.Floor(iconIndices[(int)spawnType] * IconSize / (float)iconTexture.Width)) * IconSize;
int iconSize = spawnType == SpawnType.Path ? WaypointSize : SpawnPointSize;
if (ConnectedGap != null || Ladders != null || Stairs != null || SpawnType != SpawnType.Path) { iconSize = (int)(iconSize * 1.5f); }
int iconSize = IconSize;
if (ConnectedGap != null)
if (IsSelected || IsHighlighted)
{
iconSize = (int)(iconSize * 1.5f);
}
if (Ladders != null)
{
iconSize = (int)(iconSize * 1.5f);
}
if (Stairs != null)
{
iconSize = (int)(iconSize * 1.5f);
int glowSize = (int)(iconSize * 1.5f);
GUI.Style.UIGlowCircular.Draw(spriteBatch,
new Rectangle((int)(drawPos.X - glowSize / 2), (int)(drawPos.Y - glowSize / 2), glowSize, glowSize),
Color.White);
}
spriteBatch.Draw(iconTexture,
new Rectangle((int)(drawPos.X - iconSize / 2), (int)(drawPos.Y - iconSize / 2), iconSize, iconSize),
new Rectangle(iconX, iconY, IconSize, IconSize), clr);
//GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true);
//GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White);
Sprite sprite = iconSprites[SpawnType];
if (spawnType == SpawnType.Human && AssignedJob?.Icon != null)
{
sprite = iconSprites[SpawnType.Path];
}
sprite.Draw(spriteBatch, drawPos, clr, scale: iconSize / (float)sprite.SourceRect.Width, depth: 0.001f);
sprite.RelativeOrigin = Vector2.One * 0.5f;
if (spawnType == SpawnType.Human && AssignedJob?.Icon != null)
{
AssignedJob.Icon.Draw(spriteBatch, drawPos, AssignedJob.UIColor, scale: iconSize / (float)AssignedJob.Icon.SourceRect.Width * 0.8f, depth: 0.0f);
}
foreach (MapEntity e in linkedTo)
{
GUI.DrawLine(spriteBatch,
drawPos,
new Vector2(e.DrawPosition.X, -e.DrawPosition.Y),
isObstructed ? Color.Gray : GUI.Style.Green, width: 5);
(isObstructed ? Color.Gray : GUI.Style.Green) * 0.7f, width: 5, depth: 0.002f);
}
GUI.SmallFont.DrawString(spriteBatch,
@@ -83,6 +82,14 @@ namespace Barotrauma
Color.WhiteSmoke);
}
public override bool IsMouseOn(Vector2 position)
{
if (IsHidden()) { return false; }
float dist = Vector2.DistanceSquared(position, WorldPosition);
float radius = (SpawnType == SpawnType.Path ? WaypointSize : SpawnPointSize) * 0.6f;
return dist < radius * radius;
}
private bool IsHidden()
{
if (spawnType == SpawnType.Path)
@@ -101,59 +108,72 @@ namespace Barotrauma
{
editingHUD = CreateEditingHUD();
}
if (IsSelected && PlayerInput.PrimaryMouseButtonClicked())
{
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
// Update gaps, ladders, and stairs
UpdateLinkedEntity(position, Gap.GapList, gap => ConnectedGap = gap, gap =>
if (PlayerInput.KeyDown(Keys.Space))
{
if (ConnectedGap == gap)
foreach (MapEntity e in mapEntityList)
{
ConnectedGap = null;
}
});
UpdateLinkedEntity(position, Item.ItemList, i =>
{
var ladder = i?.GetComponent<Ladder>();
if (ladder != null)
{
Ladders = ladder;
}
}, i =>
{
var ladder = i?.GetComponent<Ladder>();
if (ladder != null)
{
if (Ladders == ladder)
if (e.GetType() != typeof(WayPoint)) continue;
if (e == this) continue;
if (!Submarine.RectContains(e.Rect, position)) continue;
if (linkedTo.Contains(e))
{
Ladders = null;
linkedTo.Remove(e);
e.linkedTo.Remove(this);
}
else
{
linkedTo.Add(e);
e.linkedTo.Add(this);
}
}
}, inflate: 5);
// TODO: Cannot check the rectangle, since the rectangle is not rotated -> Need to use the collider.
//var stairList = mapEntityList.Where(me => me is Structure s && s.StairDirection != Direction.None).Select(me => me as Structure);
//UpdateLinkedEntity(position, stairList, s =>
//{
// Stairs = s;
//}, s =>
//{
// if (Stairs == s)
// {
// Stairs = null;
// }
//});
foreach (MapEntity e in mapEntityList)
}
else
{
if (e.GetType() != typeof(WayPoint)) continue;
if (e == this) continue;
if (!Submarine.RectContains(e.Rect, position)) continue;
linkedTo.Add(e);
e.linkedTo.Add(this);
// Update gaps, ladders, and stairs
UpdateLinkedEntity(position, Gap.GapList, gap => ConnectedGap = gap, gap =>
{
if (ConnectedGap == gap)
{
ConnectedGap = null;
}
});
UpdateLinkedEntity(position, Item.ItemList, i =>
{
var ladder = i?.GetComponent<Ladder>();
if (ladder != null)
{
Ladders = ladder;
}
}, i =>
{
var ladder = i?.GetComponent<Ladder>();
if (ladder != null)
{
if (Ladders == ladder)
{
Ladders = null;
}
}
}, inflate: 5);
// TODO: Cannot check the rectangle, since the rectangle is not rotated -> Need to use the collider.
//var stairList = mapEntityList.Where(me => me is Structure s && s.StairDirection != Direction.None).Select(me => me as Structure);
//UpdateLinkedEntity(position, stairList, s =>
//{
// Stairs = s;
//}, s =>
//{
// if (Stairs == s)
// {
// Stairs = null;
// }
//});
}
}
}
@@ -178,14 +198,19 @@ namespace Barotrauma
private bool ChangeSpawnType(GUIButton button, object obj)
{
GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock;
spawnType += (int)button.UserData;
if (spawnType > SpawnType.Cargo) spawnType = SpawnType.Human;
if (spawnType < SpawnType.Human) spawnType = SpawnType.Cargo;
var values = Enum.GetValues(typeof(SpawnType));
int firstIndex = 1;
int lastIndex = values.Length - 1;
if ((int)spawnType > lastIndex)
{
spawnType = (SpawnType)firstIndex;
}
if ((int)spawnType < firstIndex)
{
spawnType = (SpawnType)values.GetValue(lastIndex);
}
spawnTypeText.Text = spawnType.ToString();
return true;
}