Merge branch 'master' into new-netcode
Conflicts: Subsurface/Properties/AssemblyInfo.cs Subsurface/Source/Characters/AICharacter.cs Subsurface/Source/Characters/Animation/HumanoidAnimController.cs Subsurface/Source/Characters/Character.cs Subsurface/Source/GameMain.cs Subsurface/Source/Items/Components/Signal/Connection.cs Subsurface/Source/Items/Item.cs Subsurface/Source/Networking/GameServer.cs Subsurface/Source/Networking/GameServerLogin.cs Subsurface/Source/Physics/PhysicsBody.cs
This commit is contained in:
@@ -529,7 +529,7 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, ConvertUnits.ToDisplayUnits(new Vector2(wallAttackPos.X, -wallAttackPos.Y)) - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false);
|
||||
}
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY*20.0f, Color.Red);
|
||||
GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY*20.0f, Color.Red);
|
||||
}
|
||||
|
||||
if (selectedAiTarget != null)
|
||||
@@ -539,10 +539,10 @@ namespace Barotrauma
|
||||
new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red);
|
||||
}
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
|
||||
GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red);
|
||||
spriteBatch.DrawString(GUI.Font, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red);
|
||||
GUI.Font.DrawString(spriteBatch, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red);
|
||||
GUI.Font.DrawString(spriteBatch, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red);
|
||||
|
||||
|
||||
IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager;
|
||||
@@ -561,7 +561,7 @@ namespace Barotrauma
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y),
|
||||
Color.LightGreen);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont,
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
pathSteering.CurrentPath.Nodes[i].ID.ToString(),
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10),
|
||||
Color.LightGreen);
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Barotrauma
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y),
|
||||
Color.LightGreen);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont,
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
pathSteering.CurrentPath.Nodes[i].ID.ToString(),
|
||||
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10),
|
||||
Color.LightGreen);
|
||||
|
||||
@@ -571,7 +571,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray));
|
||||
spriteBatch.DrawString(GUI.Font, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
|
||||
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
|
||||
|
||||
foreach (RevoluteJoint joint in limbJoints)
|
||||
{
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Barotrauma
|
||||
class BackgroundSprite
|
||||
{
|
||||
public readonly BackgroundSpritePrefab Prefab;
|
||||
public Vector2 Position;
|
||||
public Vector3 Position;
|
||||
|
||||
public float Scale;
|
||||
|
||||
public float Rotation;
|
||||
|
||||
public BackgroundSprite(BackgroundSpritePrefab prefab, Vector2 position, float scale, float rotation = 0.0f)
|
||||
public BackgroundSprite(BackgroundSpritePrefab prefab, Vector3 position, float scale, float rotation = 0.0f)
|
||||
{
|
||||
this.Prefab = prefab;
|
||||
this.Position = position;
|
||||
@@ -99,15 +99,26 @@ namespace Barotrauma
|
||||
|
||||
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, false);
|
||||
|
||||
var newSprite = new BackgroundSprite(prefab,
|
||||
(Vector2)pos, Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
|
||||
var newSprite = new BackgroundSprite(prefab,
|
||||
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, false)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
|
||||
|
||||
int x = (int)Math.Floor(((Vector2)pos).X / GridSize);
|
||||
if (x < 0 || x >= sprites.GetLength(0)) continue;
|
||||
int y = (int)Math.Floor(((Vector2)pos).Y / GridSize);
|
||||
if (y < 0 || y >= sprites.GetLength(1)) continue;
|
||||
Vector2 spriteSize = newSprite.Prefab.Sprite.size * newSprite.Scale;
|
||||
|
||||
sprites[x,y].Add(newSprite);
|
||||
int minX = (int)Math.Floor((newSprite.Position.X - spriteSize.X / 2 - newSprite.Position.Z) / GridSize);
|
||||
int maxX = (int)Math.Floor((newSprite.Position.X + spriteSize.X / 2 + newSprite.Position.Z) / GridSize);
|
||||
if (minX < 0 || maxX >= sprites.GetLength(0)) continue;
|
||||
|
||||
int minY = (int)Math.Floor((newSprite.Position.Y - spriteSize.Y / 2 - newSprite.Position.Z) / GridSize);
|
||||
int maxY = (int)Math.Floor((newSprite.Position.Y + spriteSize.Y / 2 + newSprite.Position.Z) / GridSize);
|
||||
if (minY < 0 || maxY >= sprites.GetLength(1)) continue;
|
||||
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
{
|
||||
sprites[x, y].Add(newSprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +131,8 @@ namespace Barotrauma
|
||||
Rand.Range(0.0f, level.Size.X, false),
|
||||
Rand.Range(0.0f, level.Size.Y, false));
|
||||
|
||||
if (!prefab.SpawnOnWalls) return randomPos;
|
||||
|
||||
var cells = level.GetCells(randomPos);
|
||||
|
||||
if (!cells.Any()) return null;
|
||||
@@ -178,49 +191,80 @@ namespace Barotrauma
|
||||
public void DrawSprites(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
Rectangle indices = Rectangle.Empty;
|
||||
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize) - 2;
|
||||
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize);
|
||||
if (indices.X >= sprites.GetLength(0)) return;
|
||||
|
||||
indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize) - 2;
|
||||
indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize);
|
||||
if (indices.Y >= sprites.GetLength(1)) return;
|
||||
|
||||
indices.Width = (int)Math.Ceiling(cam.WorldView.Right / (float)GridSize) + 2;
|
||||
indices.Width = (int)Math.Floor(cam.WorldView.Right / (float)GridSize)+1;
|
||||
if (indices.Width < 0) return;
|
||||
indices.Height = (int)Math.Ceiling(cam.WorldView.Y / (float)GridSize) + 2;
|
||||
indices.Height = (int)Math.Floor(cam.WorldView.Y / (float)GridSize)+1;
|
||||
if (indices.Height < 0) return;
|
||||
|
||||
indices.X = Math.Max(indices.X, 0);
|
||||
indices.Y = Math.Max(indices.Y, 0);
|
||||
indices.Width = Math.Min(indices.Width, sprites.GetLength(0));
|
||||
indices.Height = Math.Min(indices.Height, sprites.GetLength(1));
|
||||
indices.Width = Math.Min(indices.Width, sprites.GetLength(0)-1);
|
||||
indices.Height = Math.Min(indices.Height, sprites.GetLength(1)-1);
|
||||
|
||||
float swingState = (float)Math.Sin(swingTimer * 0.1f);
|
||||
|
||||
List<BackgroundSprite> visibleSprites = new List<BackgroundSprite>();
|
||||
|
||||
float z = 0.0f;
|
||||
for (int x = indices.X; x < indices.Width; x++)
|
||||
for (int x = indices.X; x <= indices.Width; x++)
|
||||
{
|
||||
for (int y = indices.Y; y < indices.Height; y++)
|
||||
for (int y = indices.Y; y <= indices.Height; y++)
|
||||
{
|
||||
foreach (BackgroundSprite sprite in sprites[x, y])
|
||||
{
|
||||
sprite.Prefab.Sprite.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(sprite.Position.X, -sprite.Position.Y),
|
||||
Color.White,
|
||||
sprite.Rotation + swingState*sprite.Prefab.SwingAmount,
|
||||
sprite.Scale,
|
||||
SpriteEffects.None,
|
||||
z);
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
int drawOrderIndex = 0;
|
||||
for (int i = 0; i < visibleSprites.Count; i++)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true);
|
||||
if (visibleSprites[i] == sprite)
|
||||
{
|
||||
drawOrderIndex = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (visibleSprites[i].Position.Z > sprite.Position.Z)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawOrderIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
z += 0.0001f;
|
||||
if (drawOrderIndex >= 0)
|
||||
{
|
||||
visibleSprites.Insert(drawOrderIndex, sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (BackgroundSprite sprite in visibleSprites)
|
||||
{
|
||||
Vector2 camDiff = new Vector2(sprite.Position.X, sprite.Position.Y) - cam.WorldViewCenter;
|
||||
camDiff.Y = -camDiff.Y;
|
||||
|
||||
sprite.Prefab.Sprite.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(sprite.Position.X, -sprite.Position.Y) - camDiff * sprite.Position.Z / 10000.0f,
|
||||
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, sprite.Position.Z / 5000.0f),
|
||||
sprite.Rotation + swingState * sprite.Prefab.SwingAmount,
|
||||
sprite.Scale,
|
||||
SpriteEffects.None,
|
||||
z);
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true);
|
||||
}
|
||||
|
||||
z += 0.0001f;
|
||||
}
|
||||
}
|
||||
|
||||
private BackgroundSpritePrefab GetRandomPrefab(string levelType)
|
||||
|
||||
@@ -13,10 +13,14 @@ namespace Barotrauma
|
||||
|
||||
public readonly Vector2 Scale;
|
||||
|
||||
public bool SpawnOnWalls;
|
||||
|
||||
public readonly bool AlignWithSurface;
|
||||
|
||||
public readonly Vector2 RandomRotation;
|
||||
|
||||
public readonly Vector2 DepthRange;
|
||||
|
||||
public readonly float SwingAmount;
|
||||
|
||||
public readonly int Commonness;
|
||||
@@ -34,9 +38,13 @@ namespace Barotrauma
|
||||
|
||||
Commonness = ToolBox.GetAttributeInt(element, "commonness", 1);
|
||||
|
||||
SpawnOnWalls = ToolBox.GetAttributeBool(element, "spawnonwalls", true);
|
||||
|
||||
Scale.X = ToolBox.GetAttributeFloat(element, "minsize", 1.0f);
|
||||
Scale.Y = ToolBox.GetAttributeFloat(element, "maxsize", 1.0f);
|
||||
|
||||
DepthRange = ToolBox.GetAttributeVector2(element, "depthrange", Vector2.Zero);
|
||||
|
||||
AlignWithSurface = ToolBox.GetAttributeBool(element, "alignwithsurface", false);
|
||||
|
||||
RandomRotation = ToolBox.GetAttributeVector2(element, "randomrotation", Vector2.Zero);
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public List<Item> SpawnItems = new List<Item>();
|
||||
|
||||
|
||||
private bool enabled;
|
||||
public bool Enabled
|
||||
{
|
||||
@@ -51,12 +51,14 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == enabled) return;
|
||||
enabled = value;
|
||||
|
||||
foreach (Limb limb in AnimController.Limbs)
|
||||
{
|
||||
limb.body.Enabled = enabled;
|
||||
}
|
||||
AnimController.Collider.Enabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1617,12 +1619,12 @@ namespace Barotrauma
|
||||
{
|
||||
nameColor = Color.Red;
|
||||
}
|
||||
spriteBatch.DrawString(GUI.Font, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
spriteBatch.DrawString(GUI.Font, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.Font, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIImage(new Rectangle(0,0,30,30), HeadSprite, Alignment.TopLeft, frame);
|
||||
|
||||
SpriteFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font;
|
||||
ScalableFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font;
|
||||
|
||||
int x = 0, y = 0;
|
||||
new GUITextBlock(new Rectangle(x+60, y, 200, 20), Name, GUI.Style, frame, font);
|
||||
|
||||
@@ -54,14 +54,14 @@ namespace Barotrauma
|
||||
{
|
||||
int x = 20, y = 20;
|
||||
int width = 800, height = 500;
|
||||
|
||||
|
||||
frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.5f));
|
||||
frame.Color = Color.White * 0.4f;
|
||||
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
|
||||
listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, GUI.Style, frame);
|
||||
listBox.Color = Color.Black * 0.7f;
|
||||
|
||||
|
||||
textBox = new GUITextBox(new Rectangle(0,0,0,20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, GUI.Style, frame);
|
||||
textBox.Color = Color.Black * 0.7f;
|
||||
|
||||
|
||||
287
Subsurface/Source/Fonts/ScalableFont.cs
Normal file
287
Subsurface/Source/Fonts/ScalableFont.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpFont;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class ScalableFont
|
||||
{
|
||||
private static List<ScalableFont> FontList = new List<ScalableFont>();
|
||||
private static Library Lib = null;
|
||||
|
||||
private string filename;
|
||||
private Face face;
|
||||
private uint size;
|
||||
private int baseHeight;
|
||||
//private int lineHeight;
|
||||
private Dictionary<uint, GlyphData> texCoords;
|
||||
private List<Texture2D> textures;
|
||||
private GraphicsDevice graphicsDevice;
|
||||
|
||||
public uint Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
set
|
||||
{
|
||||
size = value;
|
||||
if (graphicsDevice!=null) RenderAtlas(graphicsDevice, charRanges, texDims, baseChar);
|
||||
}
|
||||
}
|
||||
|
||||
private uint[] charRanges;
|
||||
private int texDims;
|
||||
private uint baseChar;
|
||||
|
||||
private struct GlyphData
|
||||
{
|
||||
public int texIndex;
|
||||
public Vector2 drawOffset;
|
||||
public float advance;
|
||||
public Rectangle texCoords;
|
||||
}
|
||||
|
||||
public ScalableFont(string filename, uint size, GraphicsDevice gd=null)
|
||||
{
|
||||
if (Lib == null) Lib = new Library();
|
||||
this.filename = filename;
|
||||
this.face = null;
|
||||
foreach (ScalableFont font in FontList)
|
||||
{
|
||||
if (font.filename == filename)
|
||||
{
|
||||
this.face = font.face;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.face == null)
|
||||
{
|
||||
this.face = new Face(Lib, filename);
|
||||
}
|
||||
this.size = size;
|
||||
|
||||
this.textures = new List<Texture2D>();
|
||||
|
||||
this.texCoords = new Dictionary<uint, GlyphData>();
|
||||
|
||||
if (gd != null) RenderAtlas(gd);
|
||||
|
||||
FontList.Add(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the font into at least one texture atlas, which is simply a collection of all glyphs in the ranges defined by charRanges.
|
||||
/// Don't call this too often or with very large sizes.
|
||||
/// </summary>
|
||||
/// <param name="gd">Graphics device, required to create textures.</param>
|
||||
/// <param name="charRanges">Character ranges between each even element with their corresponding odd element. Default is 0x20 to 0xFFFF.</param>
|
||||
/// <param name="texDims">Texture dimensions. Default is 512x512.</param>
|
||||
/// <param name="baseChar">Base character used to shift all other characters downwards when rendering. Defaults to T.</param>
|
||||
public void RenderAtlas(GraphicsDevice gd, uint[] charRanges = null, int texDims = 512, uint baseChar = 0x54)
|
||||
{
|
||||
if (charRanges == null)
|
||||
{
|
||||
charRanges = new uint[] { 0x20, 0xFFFF };
|
||||
}
|
||||
this.charRanges = charRanges;
|
||||
this.texDims = texDims;
|
||||
this.baseChar = baseChar;
|
||||
|
||||
face.SetPixelSizes(0, size);
|
||||
textures.ForEach(t => t.Dispose());
|
||||
textures.Clear();
|
||||
texCoords.Clear();
|
||||
|
||||
uint[] pixelBuffer = new uint[texDims * texDims];
|
||||
for (int i = 0; i < texDims * texDims; i++)
|
||||
{
|
||||
pixelBuffer[i] = 0;
|
||||
}
|
||||
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
int texIndex = 0;
|
||||
|
||||
Vector2 currentCoords = Vector2.Zero;
|
||||
int nextY = 0;
|
||||
|
||||
face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
|
||||
baseHeight = face.Glyph.Metrics.Height.ToInt32();
|
||||
//lineHeight = baseHeight;
|
||||
for (int i = 0; i < charRanges.Count(); i += 2)
|
||||
{
|
||||
uint start = charRanges[i];
|
||||
uint end = charRanges[i + 1];
|
||||
for (uint j = start; j <= end; j++)
|
||||
{
|
||||
uint glyphIndex = face.GetCharIndex(j);
|
||||
if (glyphIndex == 0) continue;
|
||||
face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
|
||||
if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
|
||||
{
|
||||
if (face.Glyph.Metrics.HorizontalAdvance > 0)
|
||||
{
|
||||
//glyph is empty, but char still applies advance
|
||||
GlyphData blankData = new GlyphData();
|
||||
blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance;
|
||||
blankData.texIndex = -1; //indicates no texture because the glyph is empty
|
||||
texCoords.Add(j, blankData);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//stacktrace doesn't really work that well when RenderGlyph throws an exception
|
||||
face.Glyph.RenderGlyph(RenderMode.Normal);
|
||||
byte[] bitmap = face.Glyph.Bitmap.BufferData;
|
||||
int glyphWidth = face.Glyph.Bitmap.Width;
|
||||
int glyphHeight = bitmap.Count() / glyphWidth;
|
||||
|
||||
//if (glyphHeight>lineHeight) lineHeight=glyphHeight;
|
||||
|
||||
if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
|
||||
{
|
||||
throw new Exception(filename + ", " + size.ToString() + ", "+ (char)j + "; Glyph dimensions exceed texture atlas dimensions");
|
||||
}
|
||||
|
||||
nextY = Math.Max(nextY, glyphHeight + 2);
|
||||
|
||||
if (currentCoords.X + glyphWidth + 2 > texDims - 1)
|
||||
{
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y += nextY;
|
||||
nextY = 0;
|
||||
}
|
||||
if (currentCoords.Y + glyphHeight + 2 > texDims - 1)
|
||||
{
|
||||
currentCoords.X = 0;
|
||||
currentCoords.Y = 0;
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
|
||||
texIndex++;
|
||||
for (int k = 0; k < texDims * texDims; k++)
|
||||
{
|
||||
pixelBuffer[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GlyphData newData = new GlyphData();
|
||||
newData.advance = (float)face.Glyph.Metrics.HorizontalAdvance;
|
||||
newData.texIndex = texIndex;
|
||||
newData.texCoords = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight);
|
||||
newData.drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight*14/10 - face.Glyph.BitmapTop);
|
||||
texCoords.Add(j, newData);
|
||||
|
||||
for (int y = 0; y < glyphHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < glyphWidth; x++)
|
||||
{
|
||||
byte byteColor = bitmap[x + y * glyphWidth];
|
||||
pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor);
|
||||
}
|
||||
}
|
||||
|
||||
currentCoords.X += glyphWidth + 2;
|
||||
}
|
||||
textures[texIndex].SetData<uint>(pixelBuffer);
|
||||
}
|
||||
|
||||
graphicsDevice = gd;
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
|
||||
{
|
||||
if (textures.Count == 0) return;
|
||||
|
||||
int lineNum = 0;
|
||||
Vector2 currentPos = position;
|
||||
Vector2 advanceUnit = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i]=='\n')
|
||||
{
|
||||
lineNum++;
|
||||
currentPos = position;
|
||||
currentPos.X += baseHeight * 18 / 10 * lineNum * advanceUnit.Y * scale.Y;
|
||||
currentPos.Y += baseHeight * 18 / 10 * lineNum * advanceUnit.X * scale.Y;
|
||||
continue;
|
||||
}
|
||||
uint charIndex = text[i];
|
||||
GlyphData gd;
|
||||
if (texCoords.TryGetValue(charIndex, out gd))
|
||||
{
|
||||
if (gd.texIndex >= 0)
|
||||
{
|
||||
Texture2D tex = textures[gd.texIndex];
|
||||
Vector2 drawOffset;
|
||||
drawOffset.X = gd.drawOffset.X * advanceUnit.X - gd.drawOffset.Y * advanceUnit.Y;
|
||||
drawOffset.Y = gd.drawOffset.X * advanceUnit.Y + gd.drawOffset.Y * advanceUnit.X;
|
||||
|
||||
sb.Draw(tex, currentPos + drawOffset, null, gd.texCoords, origin, rotation, scale, color, se, layerDepth);
|
||||
}
|
||||
currentPos += gd.advance * advanceUnit * scale.X;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth)
|
||||
{
|
||||
DrawString(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth);
|
||||
}
|
||||
|
||||
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color)
|
||||
{
|
||||
if (textures.Count == 0) return;
|
||||
|
||||
Vector2 currentPos = position;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
currentPos.X = position.X;
|
||||
currentPos.Y += baseHeight * 18 / 10;
|
||||
continue;
|
||||
}
|
||||
uint charIndex = text[i];
|
||||
GlyphData gd;
|
||||
if (texCoords.TryGetValue(charIndex, out gd))
|
||||
{
|
||||
if (gd.texIndex >= 0)
|
||||
{
|
||||
Texture2D tex = textures[gd.texIndex];
|
||||
sb.Draw(tex, currentPos + gd.drawOffset, gd.texCoords, color);
|
||||
}
|
||||
currentPos.X += gd.advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 MeasureString(string text)
|
||||
{
|
||||
float currentLineX = 0.0f;
|
||||
Vector2 retVal = Vector2.Zero;
|
||||
retVal.Y = baseHeight*18/10;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
currentLineX = 0.0f;
|
||||
retVal.Y += baseHeight*18/10;
|
||||
continue;
|
||||
}
|
||||
uint charIndex = text[i];
|
||||
GlyphData gd;
|
||||
if (texCoords.TryGetValue(charIndex, out gd))
|
||||
{
|
||||
currentLineX += gd.advance;
|
||||
}
|
||||
retVal.X = Math.Max(retVal.X,currentLineX);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,11 +31,22 @@ namespace Barotrauma
|
||||
public static GUIStyle Style;
|
||||
|
||||
private static Texture2D t;
|
||||
public static SpriteFont Font, SmallFont, LargeFont;
|
||||
public static ScalableFont Font, SmallFont, LargeFont;
|
||||
|
||||
private static Sprite cursor;
|
||||
|
||||
private static GraphicsDevice graphicsDevice;
|
||||
public static GraphicsDevice GraphicsDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return graphicsDevice;
|
||||
}
|
||||
set
|
||||
{
|
||||
graphicsDevice = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<GUIMessage> messages = new List<GUIMessage>();
|
||||
|
||||
@@ -68,9 +79,9 @@ namespace Barotrauma
|
||||
|
||||
public static void Init(ContentManager content)
|
||||
{
|
||||
Font = ToolBox.TryLoadFont("SpriteFont1", content);
|
||||
SmallFont = ToolBox.TryLoadFont("SmallFont", content);
|
||||
LargeFont = ToolBox.TryLoadFont("LargeFont", content);
|
||||
Font = new ScalableFont("Content/Exo2-Medium.otf", 14, graphicsDevice);
|
||||
SmallFont = new ScalableFont("Content/Exo2-Light.otf", 12, graphicsDevice);
|
||||
LargeFont = new ScalableFont("Content/Code Pro Bold.otf", 22, graphicsDevice);
|
||||
|
||||
cursor = new Sprite("Content/UI/cursor.png", Vector2.Zero);
|
||||
|
||||
@@ -87,10 +98,8 @@ namespace Barotrauma
|
||||
get { return settingsMenuOpen; }
|
||||
}
|
||||
|
||||
public static void LoadContent(GraphicsDevice graphics, bool loadSounds = true)
|
||||
public static void LoadContent(bool loadSounds = true)
|
||||
{
|
||||
graphicsDevice = graphics;
|
||||
|
||||
if (loadSounds)
|
||||
{
|
||||
sounds = new Sound[Enum.GetValues(typeof(GUISoundType)).Length];
|
||||
@@ -232,7 +241,7 @@ namespace Barotrauma
|
||||
depth);
|
||||
}
|
||||
|
||||
public static void DrawString(SpriteBatch sb, Vector2 pos, string text, Color color, Color? backgroundColor=null, int backgroundPadding=0, SpriteFont font = null)
|
||||
public static void DrawString(SpriteBatch sb, Vector2 pos, string text, Color color, Color? backgroundColor=null, int backgroundPadding=0, ScalableFont font = null)
|
||||
{
|
||||
|
||||
if (font == null) font = Font;
|
||||
@@ -242,7 +251,7 @@ namespace Barotrauma
|
||||
DrawRectangle(sb, pos - Vector2.One * backgroundPadding, textSize + Vector2.One * 2.0f * backgroundPadding, (Color)backgroundColor, true);
|
||||
}
|
||||
|
||||
sb.DrawString(font, text, pos, color);
|
||||
font.DrawString(sb, text, pos, color);
|
||||
}
|
||||
|
||||
public static void DrawRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, bool isFilled = false, float depth = 0.0f, int thickness = 1)
|
||||
@@ -405,7 +414,7 @@ namespace Barotrauma
|
||||
origin = Vector2.Zero;
|
||||
}
|
||||
|
||||
sb.DrawString(Font, text, new Vector2(rect.Center.X, rect.Center.Y) , Color.White, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f);
|
||||
Font.DrawString(sb, text, new Vector2(rect.Center.X, rect.Center.Y) , Color.White, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f);
|
||||
|
||||
return clicked;
|
||||
}
|
||||
@@ -582,12 +591,12 @@ namespace Barotrauma
|
||||
|
||||
msg.Pos = MathUtils.SmoothStep(msg.Pos, currPos, deltaTime*20.0f);
|
||||
|
||||
spriteBatch.DrawString(Font, msg.Text,
|
||||
Font.DrawString(spriteBatch, msg.Text,
|
||||
new Vector2((int)msg.Pos.X - 1, (int)msg.Pos.Y - 1),
|
||||
Color.Black * alpha*0.5f, 0.0f,
|
||||
new Vector2((int)(0.5f * msg.Size.X), (int)(0.5f * msg.Size.Y)), 1.0f, SpriteEffects.None, 0.0f);
|
||||
|
||||
spriteBatch.DrawString(Font, msg.Text,
|
||||
Font.DrawString(spriteBatch, msg.Text,
|
||||
new Vector2((int)msg.Pos.X, (int)msg.Pos.Y),
|
||||
msg.Color * alpha, 0.0f,
|
||||
new Vector2((int)(0.5f * msg.Size.X), (int)(0.5f * msg.Size.Y)), 1.0f, SpriteEffects.None, 0.0f);
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Barotrauma
|
||||
set { textBlock.TextColor = value; }
|
||||
}
|
||||
|
||||
public override SpriteFont Font
|
||||
public override ScalableFont Font
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -28,7 +28,20 @@ namespace Barotrauma
|
||||
if (!Visible) return;
|
||||
if (ComponentsToUpdate.Contains(this)) return;
|
||||
ComponentsToUpdate.Add(this);
|
||||
children.ForEach(c => c.AddToGUIUpdateList());
|
||||
|
||||
try
|
||||
{
|
||||
List<GUIComponent> fixedChildren = new List<GUIComponent>(children);
|
||||
foreach (GUIComponent c in fixedChildren)
|
||||
{
|
||||
c.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.NewMessage("Error in AddToGUIUPdateList! GUIComponent runtime type: "+this.GetType().ToString()+"; children count: "+children.Count.ToString(),Color.Red);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearUpdateList()
|
||||
@@ -86,7 +99,7 @@ namespace Barotrauma
|
||||
protected Color flashColor;
|
||||
protected float flashTimer;
|
||||
|
||||
public virtual SpriteFont Font
|
||||
public virtual ScalableFont Font
|
||||
{
|
||||
get;
|
||||
set;
|
||||
@@ -367,13 +380,21 @@ namespace Barotrauma
|
||||
|
||||
}*/
|
||||
|
||||
//use a fixed list since children can change their order in the main children list
|
||||
//TODO: maybe find a more efficient way of handling changes in list order
|
||||
List<GUIComponent> fixedChildren = new List<GUIComponent>(children);
|
||||
foreach (GUIComponent c in fixedChildren)
|
||||
try
|
||||
{
|
||||
if (!c.Visible) continue;
|
||||
c.Update(deltaTime);
|
||||
//use a fixed list since children can change their order in the main children list
|
||||
//TODO: maybe find a more efficient way of handling changes in list order
|
||||
List<GUIComponent> fixedChildren = new List<GUIComponent>(children);
|
||||
foreach (GUIComponent c in fixedChildren)
|
||||
{
|
||||
if (!c.Visible) continue;
|
||||
c.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.NewMessage("Error in Update! GUIComponent runtime type: " + this.GetType().ToString() + "; children count: " + children.Count.ToString(), Color.Red);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,6 +461,23 @@ namespace Barotrauma
|
||||
|
||||
public virtual void AddChild(GUIComponent child)
|
||||
{
|
||||
if (child == null) return;
|
||||
if (child.IsParentOf(this))
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to add the parent of a GUIComponent as a child.\n" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
if (child == this)
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to add a GUIComponent as its own child\n" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
if (children.Contains(child))
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to add a the same child twice to a GUIComponent" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
|
||||
child.parent = this;
|
||||
child.UpdateDimensions(this);
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ namespace Barotrauma
|
||||
{
|
||||
public class GUIImage : GUIComponent
|
||||
{
|
||||
Sprite sprite;
|
||||
public float Rotation;
|
||||
|
||||
Rectangle sourceRect;
|
||||
private Sprite sprite;
|
||||
|
||||
private Rectangle sourceRect;
|
||||
|
||||
bool crop;
|
||||
|
||||
@@ -85,7 +87,7 @@ namespace Barotrauma
|
||||
|
||||
if (sprite != null && sprite.Texture != null)
|
||||
{
|
||||
spriteBatch.Draw(sprite.Texture, new Vector2(rect.X, rect.Y), sourceRect, currColor * (currColor.A / 255.0f), 0.0f, Vector2.Zero,
|
||||
spriteBatch.Draw(sprite.Texture, new Vector2(rect.X, rect.Y), sourceRect, currColor * (currColor.A / 255.0f), Rotation, Vector2.Zero,
|
||||
Scale, SpriteEffects.None, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,17 @@ namespace Barotrauma
|
||||
: base(new Rectangle(0,0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
Color.Black*0.5f, Alignment.TopLeft, null, parent)
|
||||
{
|
||||
if (height == 0)
|
||||
{
|
||||
string wrappedText = ToolBox.WrapText(text, width, GUI.Font);
|
||||
string[] lines = wrappedText.Split('\n');
|
||||
foreach (string line in lines)
|
||||
{
|
||||
height += (int)GUI.Font.MeasureString(line).Y;
|
||||
}
|
||||
height += 220;
|
||||
}
|
||||
|
||||
var frame = new GUIFrame(new Rectangle(0,0,width,height), null, Alignment.Center, GUI.Style, this);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 30), header, Color.Transparent, Color.White, textAlignment, GUI.Style, frame, true);
|
||||
|
||||
@@ -103,8 +103,8 @@ namespace Barotrauma
|
||||
{
|
||||
get { return caretPos; }
|
||||
}
|
||||
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent, SpriteFont font)
|
||||
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent, ScalableFont font)
|
||||
: this(rect, text, style, Alignment.TopLeft, Alignment.TopLeft, parent, false, font)
|
||||
{
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace Barotrauma
|
||||
if (textColor != null) this.textColor = (Color)textColor;
|
||||
}
|
||||
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false, SpriteFont font = null)
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false, ScalableFont font = null)
|
||||
:base (style)
|
||||
{
|
||||
this.Font = font == null ? GUI.Font : font;
|
||||
@@ -174,7 +174,7 @@ namespace Barotrauma
|
||||
|
||||
wrappedText = text;
|
||||
|
||||
Vector2 size = MeasureText(text);
|
||||
Vector2 size = MeasureText(text);
|
||||
|
||||
if (Wrap && rect.Width>0)
|
||||
{
|
||||
@@ -184,7 +184,7 @@ namespace Barotrauma
|
||||
|
||||
size = newSize;
|
||||
}
|
||||
|
||||
|
||||
if (LimitText && text.Length>1 && size.Y > rect.Height)
|
||||
{
|
||||
string[] lines = text.Split('\n');
|
||||
@@ -205,7 +205,7 @@ namespace Barotrauma
|
||||
|
||||
if (textAlignment.HasFlag(Alignment.Bottom))
|
||||
origin.Y -= (rect.Height / 2.0f - padding.W) - size.Y / 2;
|
||||
|
||||
|
||||
origin.X = (int)origin.X;
|
||||
origin.Y = (int)origin.Y;
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace Barotrauma
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
spriteBatch.DrawString(Font,
|
||||
Font.DrawString(spriteBatch,
|
||||
Wrap ? wrappedText : text,
|
||||
new Vector2(rect.X, rect.Y) + textPos + offset,
|
||||
textColor * (textColor.A / 255.0f),
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
||||
|
||||
bool caretVisible;
|
||||
float caretTimer;
|
||||
|
||||
|
||||
GUITextBlock textBlock;
|
||||
|
||||
public delegate bool OnEnterHandler(GUITextBox textBox, string text);
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override SpriteFont Font
|
||||
public override ScalableFont Font
|
||||
{
|
||||
set
|
||||
{
|
||||
@@ -131,7 +131,7 @@ namespace Barotrauma
|
||||
|
||||
if (textBlock.Text != "")
|
||||
{
|
||||
//if you attempt to display a Character that is not in your font
|
||||
/*//if you attempt to display a Character that is not in your font
|
||||
//you will get an exception, so we filter the characters
|
||||
//remove the filtering if you're using a default Character in your spritefont
|
||||
String filtered = "";
|
||||
@@ -140,7 +140,7 @@ namespace Barotrauma
|
||||
if (Font.Characters.Contains(c)) filtered += c;
|
||||
}
|
||||
|
||||
textBlock.Text = filtered;
|
||||
textBlock.Text = filtered;*/
|
||||
|
||||
if (!Wrap && Font.MeasureString(textBlock.Text).X > rect.Width)
|
||||
{
|
||||
@@ -182,6 +182,8 @@ namespace Barotrauma
|
||||
|
||||
textBlock = new GUITextBlock(new Rectangle(0,0,0,0), "", color, textColor, textAlignment, style, this);
|
||||
|
||||
Font = GUI.Font;
|
||||
|
||||
if (style != null) style.Apply(textBlock, this);
|
||||
textBlock.Padding = new Vector4(3.0f, 0.0f, 3.0f, 0.0f);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
{
|
||||
}
|
||||
|
||||
public GUITickBox(Rectangle rect, string label, Alignment alignment, SpriteFont font, GUIComponent parent)
|
||||
public GUITickBox(Rectangle rect, string label, Alignment alignment, ScalableFont font, GUIComponent parent)
|
||||
: base(null)
|
||||
{
|
||||
if (parent != null)
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Barotrauma
|
||||
|
||||
if (GUI.LargeFont!=null)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.LargeFont, loadText,
|
||||
GUI.LargeFont.DrawString(spriteBatch, loadText,
|
||||
new Vector2(GameMain.GraphicsWidth/2.0f - GUI.LargeFont.MeasureString(loadText).X/2.0f, GameMain.GraphicsHeight*0.8f),
|
||||
Color.White);
|
||||
}
|
||||
|
||||
@@ -103,6 +103,12 @@ namespace Barotrauma
|
||||
{
|
||||
get { return NetworkMember as GameClient; }
|
||||
}
|
||||
|
||||
public double TotalElapsedTime
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public GameMain()
|
||||
{
|
||||
@@ -202,6 +208,7 @@ namespace Barotrauma
|
||||
|
||||
public IEnumerable<object> Load()
|
||||
{
|
||||
GUI.GraphicsDevice = GraphicsDevice;
|
||||
GUI.Init(Content);
|
||||
|
||||
GUIComponent.Init(Window);
|
||||
@@ -215,7 +222,7 @@ namespace Barotrauma
|
||||
TitleScreen.LoadState = 1.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
GUI.LoadContent(GraphicsDevice);
|
||||
GUI.LoadContent();
|
||||
TitleScreen.LoadState = 2.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
@@ -306,6 +313,8 @@ namespace Barotrauma
|
||||
|
||||
while (Timing.Accumulator >= Timing.Step)
|
||||
{
|
||||
TotalElapsedTime = gameTime.TotalGameTime.TotalSeconds;
|
||||
|
||||
fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
|
||||
TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
|
||||
fixedTime.ElapsedGameTime = addTime;
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace Barotrauma.Items.Components
|
||||
LinkedGap.ConnectedDoor = this;
|
||||
LinkedGap.Open = openState;
|
||||
|
||||
Vector2[] corners = GetConvexHullCorners(doorRect);
|
||||
Vector2[] corners = GetConvexHullCorners(Rectangle.Empty);
|
||||
|
||||
convexHull = new ConvexHull(corners, Color.Black, item);
|
||||
if (window != Rectangle.Empty) convexHull2 = new ConvexHull(corners, Color.Black, item);
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -451,9 +451,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Output: " + (int)temperature + " kW",
|
||||
GUI.Font.DrawString(spriteBatch, "Output: " + (int)temperature + " kW",
|
||||
new Vector2(x + 450, y + 30), Color.Red);
|
||||
spriteBatch.DrawString(GUI.Font, "Grid load: " + (int)load + " kW",
|
||||
GUI.Font.DrawString(spriteBatch, "Grid load: " + (int)load + " kW",
|
||||
new Vector2(x + 600, y + 30), Color.Yellow);
|
||||
|
||||
float maxLoad = 0.0f;
|
||||
@@ -468,18 +468,18 @@ namespace Barotrauma.Items.Components
|
||||
DrawGraph(loadGraph, spriteBatch,
|
||||
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Yellow);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Shutdown Temperature: " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Shutdown Temperature: " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White);
|
||||
|
||||
//spriteBatch.DrawString(GUI.Font, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 450, y + 180), Color.White);
|
||||
//GUI.Font.DrawString(spriteBatch, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 450, y + 180), Color.White);
|
||||
|
||||
y += 300;
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White);
|
||||
DrawGraph(fissionRateGraph, spriteBatch,
|
||||
new Rectangle(x + 30, y + 30, 200, 100), 100.0f, xOffset, Color.Orange);
|
||||
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White);
|
||||
DrawGraph(coolingRateGraph, spriteBatch,
|
||||
new Rectangle(x + 320, y + 30, 200, 100), 100.0f, xOffset, Color.LightBlue);
|
||||
|
||||
|
||||
@@ -228,11 +228,11 @@ namespace Barotrauma.Items.Components
|
||||
int y = GuiFrame.Rect.Y;
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font,
|
||||
GUI.Font.DrawString(spriteBatch,
|
||||
"Charge: " + (int)charge + "/" + (int)capacity + " kWm (" + (int)((charge / capacity) * 100.0f) + " %)",
|
||||
new Vector2(x + 30, y + 30), Color.White);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
|
||||
@@ -179,8 +179,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Power: " + (int)(-currPowerConsumption) + " kW", new Vector2(x + 30, y + 30), Color.White);
|
||||
spriteBatch.DrawString(GUI.Font, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Power: " + (int)(-currPowerConsumption) + " kW", new Vector2(x + 30, y + 30), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace Barotrauma
|
||||
pos.Y = (int)pos.Y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true);
|
||||
spriteBatch.DrawString(GUI.Font, toolTip,
|
||||
GUI.Font.DrawString(spriteBatch, toolTip,
|
||||
new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)),
|
||||
Color.White, 0.0f,
|
||||
new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)),
|
||||
|
||||
@@ -618,7 +618,16 @@ namespace Barotrauma
|
||||
|
||||
if (contained.body != null)
|
||||
{
|
||||
contained.body.FarseerBody.SetTransformIgnoreContacts(ref simPos, 0.0f);
|
||||
try
|
||||
{
|
||||
contained.body.FarseerBody.SetTransformIgnoreContacts(ref simPos, 0.0f);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("SetTransformIgnoreContacts threw an exception in SetContainedItemPositions", e);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
contained.Rect =
|
||||
|
||||
@@ -604,9 +604,9 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Pressure: " + ((int)pressure - rect.Y).ToString() +
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Pressure: " + ((int)pressure - rect.Y).ToString() +
|
||||
" - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White);
|
||||
}
|
||||
|
||||
if ((IsSelected || isHighlighted) && editing)
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
|
||||
namespace Barotrauma.Lights
|
||||
{
|
||||
class CachedShadow : IDisposable
|
||||
/*class CachedShadow : IDisposable
|
||||
{
|
||||
public VertexBuffer ShadowBuffer;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
ShadowBuffer.Dispose();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
class ConvexHullList
|
||||
{
|
||||
@@ -65,17 +65,62 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
class Segment
|
||||
{
|
||||
public SegmentPoint Start;
|
||||
public SegmentPoint End;
|
||||
|
||||
public bool IsHorizontal;
|
||||
|
||||
public Segment(SegmentPoint start, SegmentPoint end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
|
||||
start.Segment = this;
|
||||
end.Segment = this;
|
||||
|
||||
IsHorizontal = Math.Abs(start.Pos.X - end.Pos.X) > Math.Abs(start.Pos.Y - end.Pos.Y);
|
||||
}
|
||||
}
|
||||
|
||||
struct SegmentPoint
|
||||
{
|
||||
public Vector2 Pos;
|
||||
public Vector2 WorldPos;
|
||||
|
||||
public Segment Segment;
|
||||
|
||||
public SegmentPoint(Vector2 pos)
|
||||
{
|
||||
Pos = pos;
|
||||
WorldPos = pos;
|
||||
|
||||
Segment = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Pos.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHull
|
||||
{
|
||||
public static List<ConvexHullList> HullLists = new List<ConvexHullList>();
|
||||
static BasicEffect shadowEffect;
|
||||
static BasicEffect penumbraEffect;
|
||||
|
||||
private Dictionary<LightSource, CachedShadow> cachedShadows;
|
||||
|
||||
private Vector2[] vertices;
|
||||
private Vector2[] losVertices;
|
||||
private int primitiveCount;
|
||||
//private Dictionary<LightSource, CachedShadow> cachedShadows;
|
||||
|
||||
public VertexBuffer ShadowBuffer;
|
||||
|
||||
Segment[] segments = new Segment[4];
|
||||
SegmentPoint[] vertices = new SegmentPoint[4];
|
||||
SegmentPoint[] losVertices = new SegmentPoint[4];
|
||||
|
||||
//private Vector2[] vertices;
|
||||
//private Vector2[] losVertices;
|
||||
|
||||
private bool[] backFacing;
|
||||
private bool[] ignoreEdge;
|
||||
@@ -95,10 +140,28 @@ namespace Barotrauma.Lights
|
||||
|
||||
}
|
||||
|
||||
private bool enabled;
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (enabled == value) return;
|
||||
enabled = value;
|
||||
LastVertexChangeTime = (float)GameMain.Instance.TotalElapsedTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The elapsed gametime when the vertices of this hull last changed
|
||||
/// </summary>
|
||||
public float LastVertexChangeTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Rectangle BoundingBox
|
||||
@@ -124,18 +187,17 @@ namespace Barotrauma.Lights
|
||||
|
||||
parentEntity = parent;
|
||||
|
||||
cachedShadows = new Dictionary<LightSource, CachedShadow>();
|
||||
//cachedShadows = new Dictionary<LightSource, CachedShadow>();
|
||||
|
||||
shadowVertices = new VertexPositionColor[6 * 2];
|
||||
penumbraVertices = new VertexPositionTexture[6];
|
||||
|
||||
//vertices = points;
|
||||
primitiveCount = points.Length;
|
||||
SetVertices(points);
|
||||
//CalculateDimensions();
|
||||
|
||||
backFacing = new bool[primitiveCount];
|
||||
ignoreEdge = new bool[primitiveCount];
|
||||
backFacing = new bool[4];
|
||||
ignoreEdge = new bool[4];
|
||||
|
||||
Enabled = true;
|
||||
|
||||
@@ -157,12 +219,14 @@ namespace Barotrauma.Lights
|
||||
|
||||
private void UpdateIgnoredEdges(ConvexHull ch)
|
||||
{
|
||||
if (ch == this) return;
|
||||
//ignore edges that are inside some other convex hull
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
if (vertices[i].X >= ch.boundingBox.X && vertices[i].X <= ch.boundingBox.Right &&
|
||||
vertices[i].Y >= ch.boundingBox.Y && vertices[i].Y <= ch.boundingBox.Bottom)
|
||||
if (vertices[i].Pos.X >= ch.boundingBox.X && vertices[i].Pos.X <= ch.boundingBox.Right &&
|
||||
vertices[i].Pos.Y >= ch.boundingBox.Y && vertices[i].Pos.Y <= ch.boundingBox.Bottom)
|
||||
{
|
||||
Vector2 p = vertices[(i + 1) % vertices.Length];
|
||||
Vector2 p = vertices[(i + 1) % vertices.Length].Pos;
|
||||
|
||||
if (p.X >= ch.boundingBox.X && p.X <= ch.boundingBox.Right &&
|
||||
p.Y >= ch.boundingBox.Y && p.Y <= ch.boundingBox.Bottom)
|
||||
@@ -179,11 +243,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
if (minX == null || vertices[i].X < minX) minX = vertices[i].X;
|
||||
if (minY == null || vertices[i].Y < minY) minY = vertices[i].Y;
|
||||
if (minX == null || vertices[i].Pos.X < minX) minX = vertices[i].Pos.X;
|
||||
if (minY == null || vertices[i].Pos.Y < minY) minY = vertices[i].Pos.Y;
|
||||
|
||||
if (maxX == null || vertices[i].X > maxX) maxX = vertices[i].X;
|
||||
if (maxY == null || vertices[i].Y > minY) maxY = vertices[i].Y;
|
||||
if (maxX == null || vertices[i].Pos.X > maxX) maxX = vertices[i].Pos.X;
|
||||
if (maxY == null || vertices[i].Pos.Y > minY) maxY = vertices[i].Pos.Y;
|
||||
}
|
||||
|
||||
boundingBox = new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
||||
@@ -191,47 +255,73 @@ namespace Barotrauma.Lights
|
||||
|
||||
public void Move(Vector2 amount)
|
||||
{
|
||||
ClearCachedShadows();
|
||||
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i] += amount;
|
||||
losVertices[i] += amount;
|
||||
vertices[i].Pos += amount;
|
||||
losVertices[i].Pos += amount;
|
||||
|
||||
segments[i].Start.Pos += amount;
|
||||
segments[i].End.Pos += amount;
|
||||
}
|
||||
|
||||
LastVertexChangeTime = (float)GameMain.Instance.TotalElapsedTime;
|
||||
|
||||
CalculateDimensions();
|
||||
}
|
||||
|
||||
public void SetVertices(Vector2[] points)
|
||||
{
|
||||
ClearCachedShadows();
|
||||
Debug.Assert(points.Length == 4, "Only rectangular convex hulls are supported");
|
||||
|
||||
vertices = points;
|
||||
losVertices = points;
|
||||
LastVertexChangeTime = (float)GameMain.Instance.TotalElapsedTime;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
vertices[i] = new SegmentPoint(points[i]);
|
||||
losVertices[i] = new SegmentPoint(points[i]);
|
||||
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
segments[i] = new Segment(vertices[i], vertices[(i + 1) % 4]);
|
||||
}
|
||||
|
||||
int margin = 0;
|
||||
|
||||
if (Math.Abs(points[0].X - points[2].X) < Math.Abs(points[0].Y - points[1].Y))
|
||||
{
|
||||
losVertices = new Vector2[] {
|
||||
new Vector2(points[0].X+margin, points[0].Y),
|
||||
new Vector2(points[1].X+margin, points[1].Y),
|
||||
new Vector2(points[2].X-margin, points[2].Y),
|
||||
new Vector2(points[3].X-margin, points[3].Y)};
|
||||
losVertices[0].Pos = new Vector2(points[0].X + margin, points[0].Y);
|
||||
losVertices[1].Pos = new Vector2(points[1].X + margin, points[1].Y);
|
||||
losVertices[2].Pos = new Vector2(points[2].X - margin, points[2].Y);
|
||||
losVertices[3].Pos = new Vector2(points[3].X - margin, points[3].Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
losVertices = new Vector2[] {
|
||||
new Vector2(points[0].X, points[0].Y +margin),
|
||||
new Vector2(points[1].X, points[1].Y - margin),
|
||||
new Vector2(points[2].X, points[2].Y - margin),
|
||||
new Vector2(points[3].X, points[3].Y + margin)};
|
||||
losVertices[0].Pos = new Vector2(points[0].X, points[0].Y + margin);
|
||||
losVertices[1].Pos = new Vector2(points[1].X, points[1].Y - margin);
|
||||
losVertices[2].Pos = new Vector2(points[2].X, points[2].Y - margin);
|
||||
losVertices[3].Pos = new Vector2(points[3].X, points[3].Y + margin);
|
||||
}
|
||||
|
||||
CalculateDimensions();
|
||||
|
||||
if (parentEntity == null || ignoreEdge == null) return;
|
||||
for (int i = 0; i<4; i++)
|
||||
{
|
||||
ignoreEdge[i] = false;
|
||||
}
|
||||
|
||||
var chList = HullLists.Find(x => x.Submarine == parentEntity.Submarine);
|
||||
if (chList != null)
|
||||
{
|
||||
foreach (ConvexHull ch in chList.List)
|
||||
{
|
||||
UpdateIgnoredEdges(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveCachedShadow(Lights.LightSource light)
|
||||
/*private void RemoveCachedShadow(Lights.LightSource light)
|
||||
{
|
||||
CachedShadow shadow = null;
|
||||
cachedShadows.TryGetValue(light, out shadow);
|
||||
@@ -251,7 +341,7 @@ namespace Barotrauma.Lights
|
||||
cachedShadow.Value.Dispose();
|
||||
}
|
||||
cachedShadows.Clear();
|
||||
}
|
||||
}*/
|
||||
|
||||
public bool Intersects(Rectangle rect)
|
||||
{
|
||||
@@ -265,6 +355,50 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
return transformedBounds.Intersects(rect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the segments that are facing towards viewPosition
|
||||
/// </summary>
|
||||
public List<Segment> GetVisibleSegments(Vector2 viewPosition)
|
||||
{
|
||||
List<Segment> visibleFaces = new List<Segment>();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (ignoreEdge[i]) continue;
|
||||
|
||||
Vector2 pos1 = vertices[i].WorldPos;
|
||||
Vector2 pos2 = vertices[(i + 1) % 4].WorldPos;
|
||||
|
||||
Vector2 middle = (pos1 + pos2) / 2;
|
||||
|
||||
Vector2 L = viewPosition - middle;
|
||||
|
||||
Vector2 N = new Vector2(
|
||||
-(pos2.Y - pos1.Y),
|
||||
pos2.X - pos1.X);
|
||||
|
||||
if (Vector2.Dot(N, L) > 0)
|
||||
{
|
||||
visibleFaces.Add(segments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return visibleFaces;
|
||||
}
|
||||
|
||||
|
||||
public void RefreshWorldPositions()
|
||||
{
|
||||
if (parentEntity == null || parentEntity.Submarine == null) return;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
vertices[i].WorldPos = vertices[i].Pos + parentEntity.Submarine.DrawPosition;
|
||||
segments[i].Start.WorldPos = segments[i].Start.Pos + parentEntity.Submarine.DrawPosition;
|
||||
segments[i].End.WorldPos = segments[i].End.Pos + parentEntity.Submarine.DrawPosition;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateShadowVertices(Vector2 lightSourcePos, bool los = true)
|
||||
{
|
||||
@@ -273,7 +407,7 @@ namespace Barotrauma.Lights
|
||||
var vertices = los ? losVertices : this.vertices;
|
||||
|
||||
//compute facing of each edge, using N*L
|
||||
for (int i = 0; i < primitiveCount; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (ignoreEdge[i])
|
||||
{
|
||||
@@ -281,12 +415,10 @@ namespace Barotrauma.Lights
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 firstVertex = new Vector2(vertices[i].X, vertices[i].Y);
|
||||
int secondIndex = (i + 1) % primitiveCount;
|
||||
Vector2 secondVertex = new Vector2(vertices[secondIndex].X, vertices[secondIndex].Y);
|
||||
Vector2 middle = (firstVertex + secondVertex) / 2;
|
||||
Vector2 firstVertex = vertices[i].Pos;
|
||||
Vector2 secondVertex = vertices[(i+1) % 4].Pos;
|
||||
|
||||
Vector2 L = lightSourcePos - middle;
|
||||
Vector2 L = lightSourcePos - ((firstVertex + secondVertex) / 2.0f);
|
||||
|
||||
Vector2 N = new Vector2(
|
||||
-(secondVertex.Y - firstVertex.Y),
|
||||
@@ -299,10 +431,10 @@ namespace Barotrauma.Lights
|
||||
//belong to the shadow
|
||||
int startingIndex = 0;
|
||||
int endingIndex = 0;
|
||||
for (int i = 0; i < primitiveCount; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int currentEdge = i;
|
||||
int nextEdge = (i + 1) % primitiveCount;
|
||||
int nextEdge = (i + 1) % 4;
|
||||
|
||||
if (backFacing[currentEdge] && !backFacing[nextEdge])
|
||||
endingIndex = nextEdge;
|
||||
@@ -315,7 +447,7 @@ namespace Barotrauma.Lights
|
||||
if (endingIndex > startingIndex)
|
||||
shadowVertexCount = endingIndex - startingIndex + 1;
|
||||
else
|
||||
shadowVertexCount = primitiveCount + 1 - startingIndex + endingIndex;
|
||||
shadowVertexCount = 4 + 1 - startingIndex + endingIndex;
|
||||
|
||||
//shadowVertices = new VertexPositionColor[shadowVertexCount * 2];
|
||||
|
||||
@@ -324,7 +456,7 @@ namespace Barotrauma.Lights
|
||||
int svCount = 0;
|
||||
while (svCount != shadowVertexCount * 2)
|
||||
{
|
||||
Vector3 vertexPos = new Vector3(vertices[currentIndex], 0.0f);
|
||||
Vector3 vertexPos = new Vector3(vertices[currentIndex].Pos, 0.0f);
|
||||
|
||||
int i = los ? svCount : svCount + 1;
|
||||
int j = los ? svCount + 1 : svCount;
|
||||
@@ -338,14 +470,13 @@ namespace Barotrauma.Lights
|
||||
shadowVertices[j] = new VertexPositionColor();
|
||||
shadowVertices[j].Color = shadowVertices[i].Color;
|
||||
|
||||
|
||||
Vector3 L2P = vertexPos - new Vector3(lightSourcePos, 0);
|
||||
L2P.Normalize();
|
||||
|
||||
shadowVertices[j].Position = new Vector3(lightSourcePos, 0) + L2P * 9000;
|
||||
|
||||
svCount += 2;
|
||||
currentIndex = (currentIndex + 1) % primitiveCount;
|
||||
currentIndex = (currentIndex + 1) % 4;
|
||||
}
|
||||
|
||||
if (los)
|
||||
@@ -358,7 +489,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
for (int n = 0; n < 4; n += 3)
|
||||
{
|
||||
Vector3 penumbraStart = new Vector3((n == 0) ? vertices[startingIndex] : vertices[endingIndex], 0.0f);
|
||||
Vector3 penumbraStart = new Vector3((n == 0) ? vertices[startingIndex].Pos : vertices[endingIndex].Pos, 0.0f);
|
||||
|
||||
penumbraVertices[n] = new VertexPositionTexture();
|
||||
penumbraVertices[n].Position = penumbraStart;
|
||||
@@ -397,6 +528,59 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ConvexHull> GetHullsInRange(Vector2 position, float range, Submarine ParentSub)
|
||||
{
|
||||
List<ConvexHull> list = new List<ConvexHull>();
|
||||
|
||||
foreach (ConvexHullList chList in ConvexHull.HullLists)
|
||||
{
|
||||
Vector2 lightPos = position;
|
||||
if (ParentSub == null)
|
||||
{
|
||||
//light and the convexhull are both outside
|
||||
if (chList.Submarine == null)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
|
||||
}
|
||||
//light is outside, convexhull inside a sub
|
||||
else
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue;
|
||||
|
||||
lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition);
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//light is inside, convexhull outside
|
||||
if (chList.Submarine == null) continue;
|
||||
|
||||
//light and convexhull are both inside the same sub
|
||||
if (chList.Submarine == ParentSub)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
//light and convexhull are inside different subs
|
||||
else
|
||||
{
|
||||
lightPos -= (chList.Submarine.Position - ParentSub.Position);
|
||||
|
||||
Rectangle subBorders = chList.Submarine.Borders;
|
||||
subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height);
|
||||
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue;
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, LightSource light, Matrix transform, bool los = true)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
@@ -415,29 +599,13 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CachedShadow cachedShadow = null;
|
||||
if (!cachedShadows.TryGetValue(light, out cachedShadow) ||
|
||||
Vector2.DistanceSquared(lightSourcePos, cachedShadow.LightPos) > 1.0f)
|
||||
{
|
||||
CalculateShadowVertices(lightSourcePos, los);
|
||||
|
||||
if (cachedShadow != null)
|
||||
{
|
||||
cachedShadow.LightPos = lightSourcePos;
|
||||
cachedShadow.ShadowBuffer.SetData(shadowVertices, 0, shadowVertices.Length);
|
||||
cachedShadow.ShadowVertexCount = shadowVertexCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedShadow = new CachedShadow(shadowVertices, lightSourcePos, shadowVertexCount, 0);
|
||||
RemoveCachedShadow(light);
|
||||
cachedShadows.Add(light, cachedShadow);
|
||||
}
|
||||
}
|
||||
|
||||
graphicsDevice.SetVertexBuffer(cachedShadow.ShadowBuffer);
|
||||
shadowVertexCount = cachedShadow.ShadowVertexCount;
|
||||
|
||||
CalculateShadowVertices(lightSourcePos, los);
|
||||
ShadowBuffer = new VertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionColor.VertexDeclaration, 6 * 2, BufferUsage.None);
|
||||
ShadowBuffer.SetData(shadowVertices, 0, shadowVertices.Length);
|
||||
|
||||
graphicsDevice.SetVertexBuffer(ShadowBuffer);
|
||||
shadowVertexCount = shadowVertices.Length;
|
||||
|
||||
DrawShadows(graphicsDevice, cam, transform, los);
|
||||
}
|
||||
@@ -493,8 +661,6 @@ namespace Barotrauma.Lights
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
ClearCachedShadows();
|
||||
|
||||
var chList = HullLists.Find(x => x.Submarine == parentEntity.Submarine);
|
||||
|
||||
if (chList != null)
|
||||
@@ -506,8 +672,6 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace Barotrauma.Lights
|
||||
public Color AmbientLight;
|
||||
|
||||
RenderTarget2D lightMap, losTexture;
|
||||
|
||||
BasicEffect lightEffect;
|
||||
|
||||
private static Texture2D alphaClearTexture;
|
||||
|
||||
@@ -60,6 +62,15 @@ namespace Barotrauma.Lights
|
||||
|
||||
losTexture = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
|
||||
if (lightEffect == null)
|
||||
{
|
||||
lightEffect = new BasicEffect(GameMain.CurrGraphicsDevice);
|
||||
lightEffect.VertexColorEnabled = false;
|
||||
|
||||
lightEffect.TextureEnabled = true;
|
||||
lightEffect.Texture = LightSource.LightTexture;
|
||||
}
|
||||
|
||||
hullAmbientLights = new Dictionary<Hull, Color>();
|
||||
smoothedHullAmbientLights = new Dictionary<Hull, Color>();
|
||||
|
||||
@@ -83,7 +94,8 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
light.NeedsHullUpdate = true;
|
||||
light.NeedsHullCheck = true;
|
||||
light.NeedsRecalculation = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,46 +144,27 @@ namespace Barotrauma.Lights
|
||||
|
||||
//clear to some small ambient light
|
||||
graphics.Clear(AmbientLight);
|
||||
graphics.BlendState = BlendState.Additive;
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, null, null, null, cam.Transform);
|
||||
|
||||
Matrix transform = cam.ShaderTransform
|
||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
|
||||
|
||||
Vector3 offset = Vector3.Zero;// new Vector3(Submarine.MainSub.DrawPosition.X, Submarine.MainSub.DrawPosition.Y, 0.0f);
|
||||
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.Color.A < 1 || light.Range < 1.0f || !light.CastShadows) continue;
|
||||
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
|
||||
//clear alpha to 1
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
//draw all shadows
|
||||
//write only to the alpha channel, which sets alpha to 0
|
||||
graphics.RasterizerState = RasterizerState.CullNone;
|
||||
graphics.BlendState = CustomBlendStates.WriteToAlpha;
|
||||
|
||||
light.DrawShadows(graphics, cam, shadowTransform);
|
||||
|
||||
//draw the light shape
|
||||
//where Alpha is 0, nothing will be written
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform);
|
||||
light.Draw(spriteBatch);
|
||||
|
||||
spriteBatch.End();
|
||||
light.Draw(spriteBatch, lightEffect, transform);
|
||||
}
|
||||
|
||||
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform);
|
||||
|
||||
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
||||
|
||||
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
|
||||
|
||||
|
||||
foreach (LightSource light in lights)
|
||||
{
|
||||
if (light.Color.A < 1 || light.Range < 1.0f || light.CastShadows) continue;
|
||||
//if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
|
||||
|
||||
light.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
if (Character.Controlled.ClosestItem != null)
|
||||
@@ -185,10 +178,6 @@ namespace Barotrauma.Lights
|
||||
Character.Controlled.ClosestCharacter.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, null, null, null, cam.Transform);
|
||||
|
||||
foreach (Hull hull in smoothedHullAmbientLights.Keys)
|
||||
{
|
||||
@@ -207,11 +196,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
|
||||
//clear alpha, to avoid messing stuff up later
|
||||
ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
//ClearAlphaToOne(graphics, spriteBatch);
|
||||
|
||||
graphics.SetRenderTarget(null);
|
||||
graphics.BlendState = BlendState.AlphaBlend;
|
||||
}
|
||||
|
||||
public void UpdateObstructVision(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Vector2 lookAtPosition)
|
||||
@@ -253,7 +242,7 @@ namespace Barotrauma.Lights
|
||||
Matrix shadowTransform = cam.ShaderTransform
|
||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
|
||||
|
||||
var convexHulls = LightSource.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine);
|
||||
var convexHulls = ConvexHull.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine);
|
||||
|
||||
if (convexHulls != null)
|
||||
{
|
||||
|
||||
@@ -15,27 +15,35 @@ namespace Barotrauma.Lights
|
||||
private List<ConvexHullList> hullsInRange;
|
||||
|
||||
private Color color;
|
||||
|
||||
private float range;
|
||||
|
||||
public SpriteEffects SpriteEffect = SpriteEffects.None;
|
||||
|
||||
|
||||
private Sprite overrideLightTexture;
|
||||
private Texture2D texture;
|
||||
|
||||
public SpriteEffects SpriteEffect = SpriteEffects.None;
|
||||
public Sprite LightSprite;
|
||||
|
||||
private Sprite overrideLightTexture;
|
||||
|
||||
public Submarine ParentSub;
|
||||
|
||||
public bool CastShadows;
|
||||
|
||||
//what was the range of the light when HullsInRange were last updated
|
||||
private float prevHullUpdateRange;
|
||||
//what was the range of the light when lightvolumes were last calculated
|
||||
private float prevCalculatedRange;
|
||||
private Vector2 prevCalculatedPosition;
|
||||
|
||||
private Vector2 prevHullUpdatePosition;
|
||||
//do we need to recheck which convex hulls are within range
|
||||
//(e.g. position or range of the lightsource has changed)
|
||||
public bool NeedsHullCheck = true;
|
||||
//do we need to recalculate the vertices of the light volume
|
||||
public bool NeedsRecalculation = true;
|
||||
|
||||
public bool NeedsHullUpdate;
|
||||
//when were the vertices of the light volume last calculated
|
||||
private float lastRecalculationTime;
|
||||
|
||||
private DynamicVertexBuffer lightVolumeBuffer;
|
||||
private DynamicIndexBuffer lightVolumeIndexBuffer;
|
||||
private int vertexCount;
|
||||
private int indexCount;
|
||||
|
||||
private Vector2 position;
|
||||
public Vector2 Position
|
||||
@@ -46,17 +54,26 @@ namespace Barotrauma.Lights
|
||||
if (position == value) return;
|
||||
position = value;
|
||||
|
||||
if (Vector2.Distance(prevHullUpdatePosition, position) < 5.0f) return;
|
||||
if (Vector2.Distance(prevCalculatedPosition, position) < 5.0f) return;
|
||||
|
||||
NeedsHullUpdate = true;
|
||||
prevHullUpdatePosition = position;
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
prevCalculatedPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
private float rotation;
|
||||
public float Rotation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return rotation; }
|
||||
set
|
||||
{
|
||||
if (rotation == value) return;
|
||||
rotation = value;
|
||||
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 WorldPosition
|
||||
@@ -90,10 +107,11 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
if (Math.Abs(prevHullUpdateRange - range) < 10.0f) return;
|
||||
if (Math.Abs(prevCalculatedRange - range) < 10.0f) return;
|
||||
|
||||
NeedsHullUpdate = true;
|
||||
prevHullUpdateRange = range;
|
||||
NeedsHullCheck = true;
|
||||
NeedsRecalculation = true;
|
||||
prevCalculatedRange = range;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,13 +148,13 @@ namespace Barotrauma.Lights
|
||||
this.color = color;
|
||||
|
||||
CastShadows = true;
|
||||
|
||||
|
||||
texture = LightTexture;
|
||||
|
||||
|
||||
GameMain.LightManager.AddLight(this);
|
||||
}
|
||||
|
||||
public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform)
|
||||
/*public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform)
|
||||
{
|
||||
if (!CastShadows) return;
|
||||
if (range < 1.0f || color.A < 0.01f) return;
|
||||
@@ -161,147 +179,318 @@ namespace Barotrauma.Lights
|
||||
foreach (ConvexHull ch in outsideHulls)
|
||||
{
|
||||
ch.DrawShadows(graphics, cam, this, shadowTransform, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private List<ConvexHull> GetHullsInRange(Submarine sub)
|
||||
/// <summary>
|
||||
/// Update the contents of ConvexHullList and check if we need to recalculate vertices
|
||||
/// </summary>
|
||||
private void RefreshConvexHullList(ConvexHullList chList, Vector2 lightPos, Submarine sub)
|
||||
{
|
||||
//find the current list of hulls in range
|
||||
var chList = hullsInRange.Find(x => x.Submarine == sub);
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
if (fullChList == null) return;
|
||||
|
||||
//not found -> create one
|
||||
if (chList == null)
|
||||
{
|
||||
chList = new ConvexHullList(sub);
|
||||
hullsInRange.Add(chList);
|
||||
}
|
||||
chList.List = fullChList.List.FindAll(ch => ch.Enabled && MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
|
||||
Vector2 lightPos = position;
|
||||
if (ParentSub == null)
|
||||
{
|
||||
//light and the convexhull are both outside
|
||||
if (sub == null)
|
||||
{
|
||||
if (NeedsHullUpdate)
|
||||
{
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
if (fullChList != null)
|
||||
chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
//light is outside, convexhull inside a sub
|
||||
else
|
||||
{
|
||||
lightPos -= sub.Position;
|
||||
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
|
||||
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//light is inside, convexhull outside
|
||||
if (sub == null) return null;
|
||||
|
||||
//light and convexhull are both inside the same sub
|
||||
if (sub == ParentSub)
|
||||
{
|
||||
if (NeedsHullUpdate)
|
||||
{
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
//light and convexhull are inside different subs
|
||||
else
|
||||
{
|
||||
if (sub.DockedTo.Contains(ParentSub) && !NeedsHullUpdate) return chList.List;
|
||||
|
||||
lightPos -= (sub.Position - ParentSub.Position);
|
||||
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
|
||||
|
||||
var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
|
||||
chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
|
||||
}
|
||||
}
|
||||
|
||||
return chList.List;
|
||||
NeedsHullCheck = true;
|
||||
}
|
||||
|
||||
public static List<ConvexHull> GetHullsInRange(Vector2 position, float range, Submarine ParentSub)
|
||||
/// <summary>
|
||||
/// Recheck which convex hulls are in range (if needed),
|
||||
/// and check if we need to recalculate vertices due to changes in the convex hulls
|
||||
/// </summary>
|
||||
private void CheckHullsInRange()
|
||||
{
|
||||
List<ConvexHull> list = new List<ConvexHull>();
|
||||
List<Submarine> subs = new List<Submarine>(Submarine.Loaded);
|
||||
subs.Add(null);
|
||||
|
||||
foreach (ConvexHullList chList in ConvexHull.HullLists)
|
||||
foreach (Submarine sub in subs)
|
||||
{
|
||||
//find the list of convexhulls that belong to the sub
|
||||
var chList = hullsInRange.Find(x => x.Submarine == sub);
|
||||
|
||||
//not found -> create one
|
||||
if (chList == null)
|
||||
{
|
||||
chList = new ConvexHullList(sub);
|
||||
hullsInRange.Add(chList);
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
|
||||
if (chList.List.Any(ch => ch.LastVertexChangeTime > lastRecalculationTime))
|
||||
{
|
||||
NeedsRecalculation = true;
|
||||
}
|
||||
|
||||
Vector2 lightPos = position;
|
||||
if (ParentSub == null)
|
||||
{
|
||||
//light and the convexhull are both outside
|
||||
if (chList.Submarine == null)
|
||||
//light and the convexhulls are both outside
|
||||
if (sub == null)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
|
||||
if (NeedsHullCheck)
|
||||
{
|
||||
RefreshConvexHullList(chList, lightPos, null);
|
||||
}
|
||||
}
|
||||
//light is outside, convexhull inside a sub
|
||||
//light is outside, convexhulls inside a sub
|
||||
else
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue;
|
||||
lightPos -= sub.Position;
|
||||
|
||||
lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition);
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders))
|
||||
{
|
||||
if (chList.List.Count > 0) NeedsRecalculation = true;
|
||||
chList.List.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
RefreshConvexHullList(chList, lightPos, sub);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
//light is inside, convexhull outside
|
||||
if (chList.Submarine == null) continue;
|
||||
|
||||
if (sub == null) continue;
|
||||
|
||||
//light and convexhull are both inside the same sub
|
||||
if (chList.Submarine == ParentSub)
|
||||
if (sub == ParentSub)
|
||||
{
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
if (NeedsHullCheck)
|
||||
{
|
||||
RefreshConvexHullList(chList, lightPos, sub);
|
||||
}
|
||||
}
|
||||
//light and convexhull are inside different subs
|
||||
else
|
||||
{
|
||||
lightPos -= (chList.Submarine.Position - ParentSub.Position);
|
||||
if (sub.DockedTo.Contains(ParentSub) && !NeedsHullCheck) continue;
|
||||
|
||||
Rectangle subBorders = chList.Submarine.Borders;
|
||||
subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height);
|
||||
lightPos -= (sub.Position - ParentSub.Position);
|
||||
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue;
|
||||
Rectangle subBorders = sub.Borders;
|
||||
subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
|
||||
|
||||
list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
|
||||
//only draw if the light overlaps with the sub
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders))
|
||||
{
|
||||
if (chList.List.Count > 0) NeedsRecalculation = true;
|
||||
chList.List.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
RefreshConvexHullList(chList, lightPos, sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
private List<Vector2> FindRaycastHits()
|
||||
{
|
||||
if (!CastShadows) return null;
|
||||
if (range < 1.0f || color.A < 0.01f) return null;
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
|
||||
var hulls = new List<ConvexHull>();// ConvexHull.GetHullsInRange(position, range, ParentSub);
|
||||
foreach (ConvexHullList chList in hullsInRange)
|
||||
{
|
||||
hulls.AddRange(chList.List);
|
||||
}
|
||||
|
||||
//find convexhull segments that are close enough and facing towards the light source
|
||||
List<Segment> visibleSegments = new List<Segment>();
|
||||
List<SegmentPoint> points = new List<SegmentPoint>();
|
||||
foreach (ConvexHull hull in hulls)
|
||||
{
|
||||
hull.RefreshWorldPositions();
|
||||
|
||||
var visibleHullSegments = hull.GetVisibleSegments(drawPos);
|
||||
visibleSegments.AddRange(visibleHullSegments);
|
||||
|
||||
foreach (Segment s in visibleHullSegments)
|
||||
{
|
||||
points.Add(s.Start);
|
||||
points.Add(s.End);
|
||||
}
|
||||
}
|
||||
|
||||
//add a square-shaped boundary to make sure we've got something to construct the triangles from
|
||||
//even if there aren't enough hull segments around the light source
|
||||
|
||||
//(might be more effective to calculate if we actually need these extra points)
|
||||
var boundaryCorners = new List<SegmentPoint> {
|
||||
new SegmentPoint(new Vector2(drawPos.X + range*2, drawPos.Y + range*2)),
|
||||
new SegmentPoint(new Vector2(drawPos.X + range*2, drawPos.Y - range*2)),
|
||||
new SegmentPoint(new Vector2(drawPos.X - range*2, drawPos.Y - range*2)),
|
||||
new SegmentPoint(new Vector2(drawPos.X - range*2, drawPos.Y + range*2))
|
||||
};
|
||||
|
||||
points.AddRange(boundaryCorners);
|
||||
|
||||
var compareCCW = new CompareSegmentPointCW(drawPos);
|
||||
points.Sort(compareCCW);
|
||||
|
||||
List<Vector2> output = new List<Vector2>();
|
||||
|
||||
//remove points that are very close to each other
|
||||
for (int i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
if (Math.Abs(points[i].WorldPos.X - points[i + 1].WorldPos.X) < 3 &&
|
||||
Math.Abs(points[i].WorldPos.Y - points[i + 1].WorldPos.Y) < 3)
|
||||
{
|
||||
points.RemoveAt(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SegmentPoint p in points)
|
||||
{
|
||||
Vector2 dir = Vector2.Normalize(p.WorldPos - drawPos);
|
||||
Vector2 dirNormal = new Vector2(-dir.Y, dir.X)*3;
|
||||
|
||||
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
|
||||
Vector2 intersection1 = RayCast(drawPos, drawPos + dir * range * 2 - dirNormal, visibleSegments);
|
||||
Vector2 intersection2 = RayCast(drawPos, drawPos + dir * range * 2 + dirNormal, visibleSegments);
|
||||
|
||||
//hit almost the same position -> only add one vertex to output
|
||||
if ((Math.Abs(intersection1.X - intersection2.X) < 5 &&
|
||||
Math.Abs(intersection1.Y - intersection2.Y) < 5))
|
||||
{
|
||||
output.Add(intersection1);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.Add(intersection1);
|
||||
output.Add(intersection2);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private Vector2 RayCast(Vector2 rayStart, Vector2 rayEnd, List<Segment> segments)
|
||||
{
|
||||
float closestDist = 0.0f;
|
||||
Vector2? closestIntersection = null;
|
||||
|
||||
foreach (Segment s in segments)
|
||||
{
|
||||
Vector2? intersection = MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, s.IsHorizontal);
|
||||
|
||||
if (intersection != null)
|
||||
{
|
||||
float dist = Vector2.Distance((Vector2)intersection, rayStart);
|
||||
if (closestIntersection == null || dist < closestDist)
|
||||
{
|
||||
closestDist = dist;
|
||||
closestIntersection = intersection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestIntersection == null ? rayEnd : (Vector2)closestIntersection;
|
||||
}
|
||||
|
||||
private void CalculateLightVertices(List<Vector2> rayCastHits)
|
||||
{
|
||||
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
|
||||
float cosAngle = (float)Math.Cos(Rotation);
|
||||
float sinAngle = -(float)Math.Sin(Rotation);
|
||||
|
||||
Vector2 uvOffset = Vector2.Zero;
|
||||
Vector2 overrideTextureDims = Vector2.One;
|
||||
if (overrideLightTexture != null)
|
||||
{
|
||||
overrideTextureDims = new Vector2(overrideLightTexture.SourceRect.Width, overrideLightTexture.SourceRect.Height);
|
||||
uvOffset = (overrideLightTexture.Origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
// Add a vertex for the center of the mesh
|
||||
vertices.Add(new VertexPositionTexture(new Vector3(position.X, position.Y, 0),
|
||||
new Vector2(0.5f, 0.5f) + uvOffset));
|
||||
|
||||
// Add all the other encounter points as vertices
|
||||
// storing their world position as UV coordinates
|
||||
foreach (Vector2 vertex in rayCastHits)
|
||||
{
|
||||
Vector2 rawDiff = vertex - drawPos;
|
||||
Vector2 diff = rawDiff;
|
||||
diff /= range*2.0f;
|
||||
if (overrideLightTexture != null)
|
||||
{
|
||||
Vector2 originDiff = diff;
|
||||
|
||||
diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle;
|
||||
diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle;
|
||||
diff *= (overrideTextureDims / overrideLightTexture.size) * 2.0f;
|
||||
|
||||
diff += uvOffset;
|
||||
}
|
||||
|
||||
vertices.Add(new VertexPositionTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
|
||||
new Vector2(0.5f, 0.5f) + diff));
|
||||
}
|
||||
|
||||
// Compute the indices to form triangles
|
||||
List<short> indices = new List<short>();
|
||||
for (int i = 0; i < rayCastHits.Count - 1; i++)
|
||||
{
|
||||
indices.Add(0);
|
||||
indices.Add((short)((i + 2) % vertices.Count));
|
||||
indices.Add((short)((i + 1) % vertices.Count));
|
||||
}
|
||||
|
||||
indices.Add(0);
|
||||
indices.Add((short)(1));
|
||||
indices.Add((short)(vertices.Count - 1));
|
||||
|
||||
vertexCount = vertices.Count;
|
||||
indexCount = indices.Count;
|
||||
|
||||
//TODO: a better way to determine the size of the vertex buffer and handle changes in size?
|
||||
//now we just create a buffer for 64 verts and make it larger if needed
|
||||
if (lightVolumeBuffer == null)
|
||||
{
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount*1.5)), BufferUsage.None);
|
||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.CurrGraphicsDevice, typeof(short), Math.Max(64*3, (int)(indexCount * 1.5)), BufferUsage.None);
|
||||
}
|
||||
else if (vertexCount > lightVolumeBuffer.VertexCount)
|
||||
{
|
||||
lightVolumeBuffer.Dispose();
|
||||
lightVolumeIndexBuffer.Dispose();
|
||||
|
||||
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionTexture.VertexDeclaration, (int)(vertexCount*1.5), BufferUsage.None);
|
||||
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.CurrGraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
|
||||
}
|
||||
|
||||
lightVolumeBuffer.SetData<VertexPositionTexture>(vertices.ToArray());
|
||||
lightVolumeIndexBuffer.SetData<short>(indices.ToArray());
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform)
|
||||
{
|
||||
CheckHullsInRange();
|
||||
|
||||
Vector3 offset = ParentSub == null ? Vector3.Zero :
|
||||
new Vector3(ParentSub.DrawPosition.X, ParentSub.DrawPosition.Y, 0.0f);
|
||||
|
||||
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
||||
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
if (range > 1.0f)
|
||||
if (range > 1.0f && false)
|
||||
{
|
||||
if (overrideLightTexture == null)
|
||||
{
|
||||
@@ -322,9 +511,38 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (LightSprite != null)
|
||||
{
|
||||
LightSprite.Draw(spriteBatch, drawPos, Color, LightSprite.Origin, -Rotation, 1, SpriteEffect);
|
||||
//LightSprite.Draw(spriteBatch, drawPos, Color, LightSprite.Origin, -Rotation, 1, SpriteEffect);
|
||||
}
|
||||
|
||||
}
|
||||
if (NeedsRecalculation)
|
||||
{
|
||||
var verts = FindRaycastHits();
|
||||
CalculateLightVertices(verts);
|
||||
|
||||
lastRecalculationTime = (float)GameMain.Instance.TotalElapsedTime;
|
||||
NeedsRecalculation = false;
|
||||
}
|
||||
|
||||
if (vertexCount == 0) return;
|
||||
|
||||
lightEffect.DiffuseColor = (new Vector3(color.R, color.G, color.B) * (color.A / 255.0f)) / 255.0f;// color.ToVector3();
|
||||
if (overrideLightTexture != null)
|
||||
{
|
||||
lightEffect.Texture = overrideLightTexture.Texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightEffect.Texture = LightTexture;
|
||||
}
|
||||
lightEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
GameMain.CurrGraphicsDevice.SetVertexBuffer(lightVolumeBuffer);
|
||||
GameMain.CurrGraphicsDevice.Indices = lightVolumeIndexBuffer;
|
||||
|
||||
GameMain.CurrGraphicsDevice.DrawIndexedPrimitives
|
||||
(
|
||||
PrimitiveType.TriangleList, 0, 0, indexCount / 3
|
||||
);
|
||||
}
|
||||
|
||||
public void FlipX()
|
||||
@@ -349,6 +567,18 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (LightSprite != null) LightSprite.Remove();
|
||||
|
||||
if (lightVolumeBuffer != null)
|
||||
{
|
||||
lightVolumeBuffer.Dispose();
|
||||
lightVolumeBuffer = null;
|
||||
}
|
||||
|
||||
if (lightVolumeIndexBuffer != null)
|
||||
{
|
||||
lightVolumeIndexBuffer.Dispose();
|
||||
lightVolumeIndexBuffer = null;
|
||||
}
|
||||
|
||||
GameMain.LightManager.RemoveLight(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace Barotrauma
|
||||
|
||||
public void DrawListLine(SpriteBatch spriteBatch, Vector2 pos, Color color)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.Font, name, pos, color);
|
||||
GUI.Font.DrawString(spriteBatch, name, pos, color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -903,31 +903,61 @@ namespace Barotrauma
|
||||
|
||||
public void CheckForErrors()
|
||||
{
|
||||
List<string> errorMsgs = new List<string>();
|
||||
|
||||
if (!Hull.hullList.Any())
|
||||
{
|
||||
DebugConsole.ThrowError("No hulls found in the submarine. Hulls determine the \"borders\" of an individual room and are required for water and air distribution to work correctly.");
|
||||
errorMsgs.Add("No hulls found in the submarine. Hulls determine the \"borders\" of an individual room and are required for water and air distribution to work correctly.");
|
||||
}
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.GetComponent<Barotrauma.Items.Components.Vent>() == null) continue;
|
||||
if (item.GetComponent<Items.Components.Vent>() == null) continue;
|
||||
|
||||
if (!item.linkedTo.Any())
|
||||
{
|
||||
DebugConsole.ThrowError("The submarine contains vents which haven't been linked to an oxygen generator. Select a vent and click an oxygen generator while holding space to link them.");
|
||||
errorMsgs.Add("The submarine contains vents which haven't been linked to an oxygen generator. Select a vent and click an oxygen generator while holding space to link them.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (WayPoint.WayPointList.Find(wp => !wp.MoveWithLevel && wp.SpawnType == SpawnType.Path) == null)
|
||||
{
|
||||
DebugConsole.ThrowError("No waypoints found in the submarine. AI controlled crew members won't be able to navigate without waypoints.");
|
||||
errorMsgs.Add("No waypoints found in the submarine. AI controlled crew members won't be able to navigate without waypoints.");
|
||||
}
|
||||
|
||||
if (WayPoint.WayPointList.Find(wp => wp.SpawnType == SpawnType.Cargo) == null)
|
||||
{
|
||||
DebugConsole.ThrowError("The submarine doesn't have spawnpoints for cargo (which are used for determining where to place bought items). "
|
||||
errorMsgs.Add("The submarine doesn't 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\".");
|
||||
}
|
||||
|
||||
if (errorMsgs.Any())
|
||||
{
|
||||
new GUIMessageBox("Warning", string.Join("\n\n", errorMsgs), 400, 0);
|
||||
}
|
||||
|
||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||
{
|
||||
if (Vector2.Distance(e.Position, HiddenSubPosition) > 20000)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(
|
||||
"Warning",
|
||||
"One or more structures have been placed very far from the submarine. Show the structures?",
|
||||
new string[] {"Yes", "No"});
|
||||
|
||||
msgBox.Buttons[0].OnClicked += (btn, obj) =>
|
||||
{
|
||||
GameMain.EditMapScreen.Cam.Position = e.WorldPosition;
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RefreshSavedSubs()
|
||||
@@ -1010,7 +1040,7 @@ namespace Barotrauma
|
||||
{
|
||||
stream = SaveUtil.DecompressFiletoStream(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed!", e);
|
||||
return null;
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Barotrauma
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true);
|
||||
|
||||
//spriteBatch.DrawString(GUI.SmallFont, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White);
|
||||
//GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White);
|
||||
|
||||
foreach (MapEntity e in linkedTo)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ namespace Barotrauma
|
||||
|
||||
|
||||
|
||||
//spriteBatch.DrawString(GUI.font, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black);
|
||||
//GUI.Font.DrawString(spriteBatch, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black);
|
||||
|
||||
|
||||
y = y + 30;
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Barotrauma.Networking
|
||||
c != '<' &&
|
||||
c != '/'));
|
||||
}
|
||||
|
||||
|
||||
public static string SanitizeName(string name)
|
||||
{
|
||||
name = name.Trim();
|
||||
@@ -130,9 +130,8 @@ namespace Barotrauma.Networking
|
||||
string rName = "";
|
||||
for (int i=0;i<name.Length;i++)
|
||||
{
|
||||
if (name[i] < 32 || name[i] > 126)
|
||||
if (name[i] < 32)
|
||||
{
|
||||
//TODO: allow safe unicode characters, this is just to prevent players from taking names that look similar but aren't the same
|
||||
rName += '?';
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1091,23 +1091,23 @@ namespace Barotrauma.Networking
|
||||
int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
|
||||
spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
|
||||
if (client.ServerConnection != null)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);
|
||||
|
||||
y += 15;
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteBatch.DrawString(GUI.Font, "Disconnected", new Vector2(x + 10, y + 25), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Disconnected", new Vector2(x + 10, y + 25), Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ namespace Barotrauma.Networking
|
||||
private ServerLog log;
|
||||
private GUIButton showLogButton;
|
||||
|
||||
private bool initiatedStartGame;
|
||||
private CoroutineHandle startGameCoroutine;
|
||||
|
||||
private GUIScrollBar clientListScrollBar;
|
||||
|
||||
public TraitorManager TraitorManager;
|
||||
@@ -398,6 +401,21 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (initiatedStartGame)
|
||||
{
|
||||
//tried to start up the game and StartGame coroutine is not running anymore
|
||||
// -> something wen't wrong during startup, re-enable start button and reset AutoRestartTimer
|
||||
if (startGameCoroutine != null && !CoroutineManager.IsCoroutineRunning(startGameCoroutine))
|
||||
{
|
||||
if (autoRestart) AutoRestartTimer = Math.Max(AutoRestartInterval, 5.0f);
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
startGameCoroutine = null;
|
||||
initiatedStartGame = false;
|
||||
}
|
||||
}
|
||||
else if (autoRestart && Screen.Selected == GameMain.NetLobbyScreen && connectedClients.Count>0)
|
||||
{
|
||||
AutoRestartTimer -= deltaTime;
|
||||
@@ -1021,13 +1039,15 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode), false);
|
||||
startGameCoroutine = GameMain.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode), false);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private IEnumerable<object> StartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
initiatedStartGame = true;
|
||||
|
||||
Item.Spawner.Clear();
|
||||
entityEventManager.Clear();
|
||||
|
||||
@@ -1037,38 +1057,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
roundStartSeed = DateTime.Now.Millisecond;
|
||||
Rand.SetSyncedSeed(roundStartSeed);
|
||||
|
||||
bool couldNotStart = false;
|
||||
|
||||
|
||||
int teamCount = 1;
|
||||
int hostTeam = 1;
|
||||
|
||||
GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, Mission.MissionTypes[GameMain.NetLobbyScreen.MissionTypeIndex]);
|
||||
|
||||
try
|
||||
{
|
||||
GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, Mission.MissionTypes[GameMain.NetLobbyScreen.MissionTypeIndex]);
|
||||
|
||||
if (GameMain.GameSession.gameMode.Mission != null &&
|
||||
GameMain.GameSession.gameMode.Mission.AssignTeamIDs(connectedClients,out hostTeam))
|
||||
{
|
||||
teamCount = 2;
|
||||
}
|
||||
|
||||
GameMain.GameSession.StartShift(GameMain.NetLobbyScreen.LevelSeed, teamCount > 1);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
if (GameMain.GameSession.gameMode.Mission != null &&
|
||||
GameMain.GameSession.gameMode.Mission.AssignTeamIDs(connectedClients,out hostTeam))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to start a new round", e);
|
||||
|
||||
//try again in >5 seconds
|
||||
if (autoRestart) AutoRestartTimer = Math.Max(AutoRestartInterval, 5.0f);
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
couldNotStart = true;
|
||||
teamCount = 2;
|
||||
}
|
||||
|
||||
if (couldNotStart) yield return CoroutineStatus.Failure;
|
||||
GameMain.GameSession.StartShift(GameMain.NetLobbyScreen.LevelSeed, teamCount > 1);
|
||||
|
||||
GameServer.Log("Starting a new round...", Color.Cyan);
|
||||
GameServer.Log("Submarine: " + selectedSub.Name, Color.Cyan);
|
||||
@@ -1183,6 +1184,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
|
||||
gameStarted = true;
|
||||
initiatedStartGame = false;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
@@ -1658,14 +1660,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
|
||||
spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
|
||||
|
||||
int resentMessages = 0;
|
||||
|
||||
@@ -1685,10 +1687,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (y >= startY && y < startY + height - 120)
|
||||
{
|
||||
spriteBatch.DrawString(GUI.SmallFont, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor);
|
||||
GUI.SmallFont.DrawString(spriteBatch, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor);
|
||||
}
|
||||
if (y + 25 >= startY && y < startY + height - 130) spriteBatch.DrawString(GUI.SmallFont, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor);
|
||||
if (y + 25 >= startY && y < startY + height - 130) GUI.SmallFont.DrawString(spriteBatch, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor);
|
||||
|
||||
resentMessages += (int)c.Connection.Statistics.ResentMessages;
|
||||
|
||||
|
||||
@@ -71,24 +71,24 @@ namespace Barotrauma.Networking
|
||||
|
||||
graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont,
|
||||
GUI.SmallFont.DrawString(spriteBatch,
|
||||
"Peak received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].LargestValue()) + "/s " +
|
||||
"Avg received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].Average()) + "/s",
|
||||
new Vector2(rect.X + 10, rect.Y + 10), Color.Cyan);
|
||||
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " +
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " +
|
||||
"Avg sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].Average()) + "/s",
|
||||
new Vector2(rect.X + 10, rect.Y + 30), Color.Orange);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s",
|
||||
new Vector2(rect.X + 10, rect.Y + 50), Color.Red);
|
||||
#if DEBUG
|
||||
int y = 10;
|
||||
|
||||
foreach (KeyValuePair<string, long> msgBytesSent in server.messageCount.OrderBy(key => -key.Value))
|
||||
{
|
||||
spriteBatch.DrawString(GUI.SmallFont, msgBytesSent.Key + ": " + MathUtils.GetBytesReadable(msgBytesSent.Value),
|
||||
GUI.SmallFont.DrawString(spriteBatch, msgBytesSent.Key + ": " + MathUtils.GetBytesReadable(msgBytesSent.Value),
|
||||
new Vector2(rect.Right - 200, rect.Y + y), Color.Red);
|
||||
|
||||
y += 15;
|
||||
|
||||
@@ -139,11 +139,11 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
sb.AppendLine("Server (" + (GameMain.Server.GameStarted ? "Round had started)" : "Round hand't been started)"));
|
||||
sb.AppendLine("Server (" + (GameMain.Server.GameStarted ? "Round had started)" : "Round hadn't been started)"));
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
sb.AppendLine("Client (" + (GameMain.Client.GameStarted ? "Round had started)" : "Round hand't been started)"));
|
||||
sb.AppendLine("Client (" + (GameMain.Client.GameStarted ? "Round had started)" : "Round hadn't been started)"));
|
||||
}
|
||||
|
||||
sb.AppendLine("\n");
|
||||
@@ -157,7 +157,7 @@ namespace Barotrauma
|
||||
sb.AppendLine("\n");
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 10; i-- )
|
||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i-- )
|
||||
{
|
||||
sb.AppendLine(" "+DebugConsole.Messages[i].Time+" - "+DebugConsole.Messages[i].Text);
|
||||
}
|
||||
|
||||
@@ -309,9 +309,8 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
cam.Position = Submarine.HiddenSubStartPosition;
|
||||
|
||||
Submarine.MainSub = new Submarine(Path.Combine(Submarine.SavePath, "Unnamed.sub"), "", false);
|
||||
cam.Position = Submarine.MainSub.Position;
|
||||
}
|
||||
|
||||
SoundPlayer.OverrideMusicType = "none";
|
||||
@@ -419,6 +418,9 @@ namespace Barotrauma
|
||||
|
||||
private void CreateSaveScreen()
|
||||
{
|
||||
if (characterMode) ToggleCharacterMode();
|
||||
if (wiringMode) ToggleWiringMode();
|
||||
|
||||
int width = 400, height = 400;
|
||||
|
||||
int y = 0;
|
||||
@@ -503,6 +505,9 @@ namespace Barotrauma
|
||||
|
||||
private bool CreateLoadScreen(GUIButton button, object obj)
|
||||
{
|
||||
if (characterMode) ToggleCharacterMode();
|
||||
if (wiringMode) ToggleWiringMode();
|
||||
|
||||
Submarine.RefreshSavedSubs();
|
||||
|
||||
int width = 300, height = 400;
|
||||
@@ -588,8 +593,7 @@ namespace Barotrauma
|
||||
Submarine.MainSub = selectedSub;
|
||||
selectedSub.Load(true);
|
||||
|
||||
//nameBox.Text = selectedSub.Name;
|
||||
//descriptionBox.Text = ToolBox.LimitString(selectedSub.Description,15);
|
||||
cam.Position = Submarine.MainSub.Position + Submarine.MainSub.HiddenSubPosition;
|
||||
|
||||
loadFrame = null;
|
||||
|
||||
@@ -598,10 +602,14 @@ namespace Barotrauma
|
||||
|
||||
private bool SelectTab(GUIButton button, object obj)
|
||||
{
|
||||
if (characterMode) ToggleCharacterMode();
|
||||
if (wiringMode) ToggleWiringMode();
|
||||
|
||||
selectedTab = (int)obj;
|
||||
|
||||
var searchBox = GUItabs[selectedTab].GetChild<GUITextBox>();
|
||||
ClearFilter(searchBox, null);
|
||||
searchBox.Text = "";
|
||||
|
||||
searchBox.AddToGUIUpdateList();
|
||||
searchBox.Select();
|
||||
@@ -901,22 +909,28 @@ namespace Barotrauma
|
||||
wiringToolPanel.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
if (loadFrame != null)
|
||||
{
|
||||
loadFrame.AddToGUIUpdateList();
|
||||
}
|
||||
else if (saveFrame != null)
|
||||
{
|
||||
saveFrame.AddToGUIUpdateList();
|
||||
}
|
||||
else if (selectedTab > -1)
|
||||
{
|
||||
GUItabs[selectedTab].AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
if ((characterMode || wiringMode) && dummyCharacter != null)
|
||||
{
|
||||
CharacterHUD.AddToGUIUpdateList(dummyCharacter);
|
||||
if (dummyCharacter.SelectedConstruction != null)
|
||||
{
|
||||
dummyCharacter.SelectedConstruction.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (loadFrame != null)
|
||||
{
|
||||
loadFrame.AddToGUIUpdateList();
|
||||
}
|
||||
else if (saveFrame != null)
|
||||
{
|
||||
saveFrame.AddToGUIUpdateList();
|
||||
}
|
||||
else if (selectedTab > -1)
|
||||
{
|
||||
GUItabs[selectedTab].AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
GUI.AddToGUIUpdateList();
|
||||
@@ -1064,7 +1078,7 @@ namespace Barotrauma
|
||||
graphics.Clear(new Color(0.051f, 0.149f, 0.271f, 1.0f));
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch, new Vector2(0.0f, -cam.WorldView.Y), new Vector2(0.0f, -(cam.WorldView.Y - cam.WorldView.Height)), Color.White*0.5f, 1.0f, (int)(2.0f/cam.Zoom));
|
||||
GUI.DrawLine(spriteBatch, new Vector2(Submarine.MainSub.HiddenSubPosition.X, -cam.WorldView.Y), new Vector2(Submarine.MainSub.HiddenSubPosition.X, -(cam.WorldView.Y - cam.WorldView.Height)), Color.White * 0.5f, 1.0f, (int)(2.0f / cam.Zoom));
|
||||
GUI.DrawLine(spriteBatch, new Vector2(cam.WorldView.X, -Submarine.MainSub.HiddenSubPosition.Y), new Vector2(cam.WorldView.Right, -Submarine.MainSub.HiddenSubPosition.Y), Color.White * 0.5f, 1.0f, (int)(2.0f / cam.Zoom));
|
||||
}
|
||||
|
||||
@@ -1084,6 +1098,11 @@ namespace Barotrauma
|
||||
|
||||
spriteBatch.Begin();
|
||||
|
||||
if (Submarine.MainSub != null)
|
||||
{
|
||||
DrawSubmarineIndicator(spriteBatch, Submarine.MainSub, Color.LightBlue * 0.5f);
|
||||
}
|
||||
|
||||
leftPanel.Draw(spriteBatch);
|
||||
topPanel.Draw(spriteBatch);
|
||||
|
||||
|
||||
@@ -443,26 +443,5 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DrawSubmarineIndicator(SpriteBatch spriteBatch, Submarine submarine, Color color)
|
||||
{
|
||||
Vector2 subDiff = submarine.WorldPosition - cam.WorldViewCenter;
|
||||
|
||||
if (Math.Abs(subDiff.X) > cam.WorldView.Width || Math.Abs(subDiff.Y) > cam.WorldView.Height)
|
||||
{
|
||||
Vector2 normalizedSubDiff = Vector2.Normalize(subDiff);
|
||||
|
||||
Vector2 iconPos =
|
||||
cam.WorldToScreen(cam.WorldViewCenter) +
|
||||
new Vector2(normalizedSubDiff.X * GameMain.GraphicsWidth * 0.4f, -normalizedSubDiff.Y * GameMain.GraphicsHeight * 0.4f);
|
||||
|
||||
GUI.SubmarineIcon.Draw(spriteBatch, iconPos, color);
|
||||
|
||||
Vector2 arrowOffset = normalizedSubDiff * GUI.SubmarineIcon.size.X * 0.7f;
|
||||
arrowOffset.Y = -arrowOffset.Y;
|
||||
GUI.Arrow.Draw(spriteBatch, iconPos + arrowOffset, color, MathUtils.VectorToAngle(arrowOffset) + MathHelper.PiOver2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace Barotrauma
|
||||
|
||||
frame.ToolTip = ep.Description;
|
||||
|
||||
SpriteFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
||||
ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(50, 0, 0, 25),
|
||||
|
||||
@@ -515,7 +515,7 @@ namespace Barotrauma
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, null);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White);
|
||||
GUI.Font.DrawString(spriteBatch, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White);
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
@@ -540,11 +540,18 @@ namespace Barotrauma
|
||||
infoButton.UserData = -1;
|
||||
infoButton.OnClicked += ViewJobInfo;
|
||||
|
||||
GUIButton upButton = new GUIButton(new Rectangle(30, 2, 15, 15), "^", GUI.Style, jobText);
|
||||
GUIButton upButton = new GUIButton(new Rectangle(30, 2, 15, 15), "", GUI.Style, jobText);
|
||||
//TODO: make GUIImages align correctly when scaled/rotated
|
||||
//so there's no need to do this ↓
|
||||
new GUIImage(new Rectangle(3,2,0,0), GUI.Arrow, Alignment.Center, upButton).Scale = 0.6f;
|
||||
upButton.UserData = -1;
|
||||
upButton.OnClicked += ChangeJobPreference;
|
||||
|
||||
GUIButton downButton = new GUIButton(new Rectangle(50, 2, 15, 15), "˅", GUI.Style, jobText);
|
||||
GUIButton downButton = new GUIButton(new Rectangle(50, 2, 15, 15), "", GUI.Style, jobText);
|
||||
var downArrow = new GUIImage(new Rectangle(13,14,0,0), GUI.Arrow, Alignment.Center, downButton);
|
||||
downArrow.Rotation = MathHelper.Pi;
|
||||
downArrow.Scale = 0.6f;
|
||||
|
||||
downButton.UserData = 1;
|
||||
downButton.OnClicked += ChangeJobPreference;
|
||||
}
|
||||
|
||||
@@ -75,5 +75,25 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected void DrawSubmarineIndicator(SpriteBatch spriteBatch, Submarine submarine, Color color)
|
||||
{
|
||||
Vector2 subDiff = submarine.WorldPosition - Cam.WorldViewCenter;
|
||||
|
||||
if (Math.Abs(subDiff.X) > Cam.WorldView.Width || Math.Abs(subDiff.Y) > Cam.WorldView.Height)
|
||||
{
|
||||
Vector2 normalizedSubDiff = Vector2.Normalize(subDiff);
|
||||
|
||||
Vector2 iconPos =
|
||||
Cam.WorldToScreen(Cam.WorldViewCenter) +
|
||||
new Vector2(normalizedSubDiff.X * GameMain.GraphicsWidth * 0.4f, -normalizedSubDiff.Y * GameMain.GraphicsHeight * 0.4f);
|
||||
|
||||
GUI.SubmarineIcon.Draw(spriteBatch, iconPos, color);
|
||||
|
||||
Vector2 arrowOffset = normalizedSubDiff * GUI.SubmarineIcon.size.X * 0.7f;
|
||||
arrowOffset.Y = -arrowOffset.Y;
|
||||
GUI.Arrow.Draw(spriteBatch, iconPos + arrowOffset, color, MathUtils.VectorToAngle(arrowOffset) + MathHelper.PiOver2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Barotrauma
|
||||
if (n > 0) columnX[n] += columnX[n - 1];
|
||||
}
|
||||
|
||||
SpriteFont font = GUI.SmallFont; // serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font;
|
||||
ScalableFont font = GUI.SmallFont; // serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font;
|
||||
|
||||
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.Style, menu).Font = font;
|
||||
|
||||
|
||||
@@ -381,6 +381,10 @@ namespace Barotrauma.Sounds
|
||||
|
||||
Instance = this;
|
||||
underlyingThread = new Thread(EnsureBuffersFilled) { Priority = ThreadPriority.Lowest };
|
||||
|
||||
//background threads are automatically stopped when all foreground threads have been stopped
|
||||
// -> the streaming thread won't stay running in the background if the main thread crashes
|
||||
underlyingThread.IsBackground = true;
|
||||
underlyingThread.Start();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
||||
if (loadedSound.filePath == file) oggSound = loadedSound.oggSound;
|
||||
}
|
||||
|
||||
if (oggSound == null)
|
||||
if (oggSound == null && !SoundManager.Disabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -198,8 +198,8 @@ namespace Barotrauma
|
||||
return sourceIndex;
|
||||
}
|
||||
|
||||
return SoundManager.Loop(this, sourceIndex, relativePos/100.0f, volume);
|
||||
|
||||
alSourceId = SoundManager.Loop(this, sourceIndex, relativePos / 100.0f, volume);
|
||||
return alSourceId;
|
||||
}
|
||||
|
||||
public bool IsPlaying
|
||||
@@ -210,26 +210,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//public int Loop(float volume = 1.0f)
|
||||
//{
|
||||
// return SoundManager.Loop(this, volume);
|
||||
//}
|
||||
|
||||
//public void Pause()
|
||||
//{
|
||||
// SoundManager.Pause(this);
|
||||
//}
|
||||
|
||||
//public void Resume()
|
||||
//{
|
||||
// SoundManager.Resume(this);
|
||||
//}
|
||||
|
||||
//public void Stop()
|
||||
//{
|
||||
// SoundManager.Stop(this);
|
||||
//}
|
||||
|
||||
public static void OnGameEnd()
|
||||
{
|
||||
List<Sound> removableSounds = loadedSounds.FindAll(s => s.destroyOnGameEnd);
|
||||
@@ -268,17 +248,19 @@ namespace Barotrauma
|
||||
|
||||
public static void StartStream(string file, float volume = 1.0f)
|
||||
{
|
||||
if (SoundManager.Disabled) return;
|
||||
stream = SoundManager.StartStream(file, volume);
|
||||
}
|
||||
|
||||
public static void StreamVolume(float volume = 1.0f)
|
||||
{
|
||||
if (SoundManager.Disabled) return;
|
||||
stream.Volume = volume;
|
||||
}
|
||||
|
||||
public static void StopStream()
|
||||
{
|
||||
if (stream!=null) SoundManager.StopStream();
|
||||
if (stream != null) SoundManager.StopStream();
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
|
||||
@@ -9,6 +9,12 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
static class SoundManager
|
||||
{
|
||||
public static bool Disabled
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public const int DefaultSourceCount = 16;
|
||||
|
||||
private static readonly List<int> alSources = new List<int>();
|
||||
@@ -26,9 +32,17 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
var availableDevices = AudioContext.AvailableDevices;
|
||||
if (availableDevices.Count == 0)
|
||||
{
|
||||
DebugConsole.ThrowError("No audio devices found. Disabling audio playback.");
|
||||
Disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AC = new AudioContext();
|
||||
AC = new AudioContext();
|
||||
ALHelper.Check();
|
||||
}
|
||||
catch (DllNotFoundException e)
|
||||
@@ -55,11 +69,14 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static int Play(Sound sound, float volume = 1.0f)
|
||||
{
|
||||
if (Disabled) return -1;
|
||||
return Play(sound, Vector2.Zero, volume, 0.0f);
|
||||
}
|
||||
|
||||
public static int Play(Sound sound, Vector2 position, float volume = 1.0f, float lowPassGain = 0.0f, bool loop=false)
|
||||
{
|
||||
if (Disabled) return -1;
|
||||
|
||||
for (int i = 1; i < DefaultSourceCount; i++)
|
||||
{
|
||||
//find a source that's free to use (not playing or paused)
|
||||
@@ -85,11 +102,15 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static int Loop(Sound sound, int sourceIndex, float volume = 1.0f)
|
||||
{
|
||||
if (Disabled) return -1;
|
||||
|
||||
return Loop(sound,sourceIndex, Vector2.Zero, volume);
|
||||
}
|
||||
|
||||
public static int Loop(Sound sound, int sourceIndex, Vector2 position, float volume = 1.0f)
|
||||
{
|
||||
if (Disabled) return -1;
|
||||
|
||||
if (!MathUtils.IsValid(volume))
|
||||
{
|
||||
volume = 0.0f;
|
||||
@@ -111,6 +132,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Pause(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return;
|
||||
|
||||
if (AL.GetSourceState(alSources[sourceIndex]) != ALSourceState.Playing)
|
||||
return;
|
||||
|
||||
@@ -120,6 +143,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Resume(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return;
|
||||
|
||||
if (AL.GetSourceState(alSources[sourceIndex]) != ALSourceState.Paused)
|
||||
return;
|
||||
|
||||
@@ -129,6 +154,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Stop(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return;
|
||||
|
||||
if (sourceIndex < 1) return;
|
||||
|
||||
var state = AL.GetSourceState(alSources[sourceIndex]);
|
||||
@@ -143,6 +170,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static Sound GetPlayingSound(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return null;
|
||||
|
||||
if (sourceIndex < 1 || sourceIndex>alSources.Count-1) return null;
|
||||
|
||||
if (AL.GetSourceState(alSources[sourceIndex]) != ALSourceState.Playing) return null;
|
||||
@@ -152,6 +181,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static bool IsPlaying(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return false;
|
||||
|
||||
if (sourceIndex < 1 || sourceIndex>alSources.Count-1) return false;
|
||||
|
||||
return AL.GetSourceState(alSources[sourceIndex]) == ALSourceState.Playing;
|
||||
@@ -159,6 +190,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static bool IsPaused(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return false;
|
||||
|
||||
if (sourceIndex < 1 || sourceIndex > alSources.Count - 1) return false;
|
||||
|
||||
return AL.GetSourceState(alSources[sourceIndex]) == ALSourceState.Paused;
|
||||
@@ -166,6 +199,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static bool IsLooping(int sourceIndex)
|
||||
{
|
||||
if (Disabled) return false;
|
||||
if (sourceIndex < 1 || sourceIndex > alSources.Count - 1) return false;
|
||||
|
||||
bool isLooping;
|
||||
@@ -177,6 +211,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Volume(int sourceIndex, float volume)
|
||||
{
|
||||
if (Disabled) return;
|
||||
|
||||
AL.Source(alSources[sourceIndex], ALSourcef.Gain, volume * MasterVolume);
|
||||
ALHelper.Check();
|
||||
}
|
||||
@@ -187,6 +223,7 @@ namespace Barotrauma.Sounds
|
||||
get { return lowPassHfGain; }
|
||||
set
|
||||
{
|
||||
if (Disabled) return;
|
||||
if (ALHelper.Efx.IsInitialized)
|
||||
{
|
||||
lowPassHfGain = value;
|
||||
@@ -200,7 +237,6 @@ namespace Barotrauma.Sounds
|
||||
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
|
||||
ALHelper.Check();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,7 +244,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void UpdateSoundPosition(int sourceIndex, Vector2 position, float baseVolume = 1.0f)
|
||||
{
|
||||
if (sourceIndex < 1) return;
|
||||
if (sourceIndex < 1 || Disabled) return;
|
||||
|
||||
if (!MathUtils.IsValid(position))
|
||||
{
|
||||
@@ -229,6 +265,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static OggStream StartStream(string file, float volume = 1.0f)
|
||||
{
|
||||
if (Disabled) return null;
|
||||
|
||||
if (oggStreamer == null)
|
||||
oggStreamer = new OggStreamer();
|
||||
|
||||
@@ -244,7 +282,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void StopStream()
|
||||
{
|
||||
if (oggStream!=null) oggStream.Stop();
|
||||
if (oggStream != null) oggStream.Stop();
|
||||
}
|
||||
|
||||
public static void ClearAlSource(int bufferId)
|
||||
@@ -260,6 +298,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
if (Disabled) return;
|
||||
|
||||
if (ALHelper.Efx.IsInitialized)
|
||||
ALHelper.Efx.DeleteFilter(lowpassFilterId);
|
||||
|
||||
|
||||
1839
Subsurface/Source/Utils/Homoglyphs.cs
Normal file
1839
Subsurface/Source/Utils/Homoglyphs.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -207,57 +207,111 @@ namespace Barotrauma
|
||||
|
||||
return a1 + t * b;
|
||||
}
|
||||
|
||||
public static Vector2? GetAxisAlignedLineIntersection(Vector2 a1, Vector2 a2, Vector2 axisAligned1, Vector2 axisAligned2, bool isHorizontal)
|
||||
{
|
||||
if (!isHorizontal)
|
||||
{
|
||||
if (Math.Sign(a1.X - axisAligned1.X) == Math.Sign(a2.X - axisAligned1.X))
|
||||
return null;
|
||||
|
||||
float s = (a2.Y - a1.Y) / (a2.X - a1.X);
|
||||
float y = a1.Y + (axisAligned1.X - a1.X) * s;
|
||||
|
||||
if (axisAligned1.Y < axisAligned2.Y)
|
||||
{
|
||||
if (y < axisAligned1.Y) return null;
|
||||
if (y > axisAligned2.Y) return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y > axisAligned1.Y) return null;
|
||||
if (y < axisAligned2.Y) return null;
|
||||
}
|
||||
|
||||
return new Vector2(axisAligned1.X, y);
|
||||
}
|
||||
else //horizontal line
|
||||
{
|
||||
if (Math.Sign(a1.Y - axisAligned1.Y) == Math.Sign(a2.Y - axisAligned1.Y))
|
||||
return null;
|
||||
|
||||
float s = (a2.X - a1.X) / (a2.Y - a1.Y);
|
||||
float x = a1.X + (axisAligned1.Y - a1.Y) * s;
|
||||
|
||||
if (axisAligned1.X < axisAligned2.X)
|
||||
{
|
||||
if (x < axisAligned1.X) return null;
|
||||
if (x > axisAligned2.X) return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x > axisAligned1.X) return null;
|
||||
if (x < axisAligned2.X) return null;
|
||||
}
|
||||
|
||||
return new Vector2(x, axisAligned1.Y);
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector2? GetLineRectangleIntersection(Vector2 a1, Vector2 a2, Rectangle rect)
|
||||
{
|
||||
Vector2? intersection = GetLineIntersection(a1, a2,
|
||||
Vector2? intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y));
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
intersection = GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y-rect.Height),
|
||||
new Vector2(rect.Right, rect.Y-rect.Height));
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
intersection = GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.X, rect.Y - rect.Height));
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
return GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.Right, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height));
|
||||
true);
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y-rect.Height),
|
||||
new Vector2(rect.Right, rect.Y-rect.Height),
|
||||
true);
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.X, rect.Y - rect.Height),
|
||||
false);
|
||||
|
||||
if (intersection != null) return intersection;
|
||||
|
||||
return GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.Right, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height),
|
||||
false);
|
||||
}
|
||||
|
||||
public static List<Vector2> GetLineRectangleIntersections(Vector2 a1, Vector2 a2, Rectangle rect)
|
||||
{
|
||||
List<Vector2> intersections = new List<Vector2>();
|
||||
|
||||
Vector2? intersection = GetLineIntersection(a1, a2,
|
||||
Vector2? intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y));
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y - rect.Height),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height));
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.X, rect.Y - rect.Height));
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetLineIntersection(a1, a2,
|
||||
new Vector2(rect.Right, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height));
|
||||
true);
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y - rect.Height),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height),
|
||||
true);
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
new Vector2(rect.X, rect.Y - rect.Height),
|
||||
false);
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
intersection = GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.Right, rect.Y),
|
||||
new Vector2(rect.Right, rect.Y - rect.Height),
|
||||
false);
|
||||
|
||||
if (intersection != null) intersections.Add((Vector2)intersection);
|
||||
|
||||
@@ -276,15 +330,16 @@ namespace Barotrauma
|
||||
public static bool CircleIntersectsRectangle(Vector2 circlePos, float radius, Rectangle rect)
|
||||
{
|
||||
float xDist = Math.Abs(circlePos.X - rect.Center.X);
|
||||
float yDist = Math.Abs(circlePos.Y - rect.Center.Y);
|
||||
|
||||
int halfWidth = rect.Width / 2;
|
||||
int halfHeight = rect.Height / 2;
|
||||
|
||||
if (xDist > (halfWidth + radius)) { return false; }
|
||||
if (xDist <= (halfWidth)) { return true; }
|
||||
if (yDist > (halfHeight + radius)) { return false; }
|
||||
|
||||
float yDist = Math.Abs(circlePos.Y - rect.Center.Y);
|
||||
int halfHeight = rect.Height / 2;
|
||||
|
||||
if (yDist > (halfHeight + radius)) { return false; }
|
||||
if (xDist <= (halfWidth)) { return true; }
|
||||
if (yDist <= (halfHeight)) { return true; }
|
||||
|
||||
float distSqX = xDist - halfWidth;
|
||||
@@ -475,4 +530,18 @@ namespace Barotrauma
|
||||
return Math.Sign(d2 - d1);
|
||||
}
|
||||
}
|
||||
|
||||
class CompareSegmentPointCW : IComparer<Lights.SegmentPoint>
|
||||
{
|
||||
private Vector2 center;
|
||||
|
||||
public CompareSegmentPointCW(Vector2 center)
|
||||
{
|
||||
this.center = center;
|
||||
}
|
||||
public int Compare(Lights.SegmentPoint a, Lights.SegmentPoint b)
|
||||
{
|
||||
return -CompareCCW.Compare(a.WorldPos, b.WorldPos, center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Barotrauma
|
||||
Directory.CreateDirectory(tempPath);
|
||||
try
|
||||
{
|
||||
ClearFolder(tempPath);
|
||||
ClearFolder(tempPath, new string[] { GameMain.GameSession.Submarine.FilePath });
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma
|
||||
|
||||
try
|
||||
{
|
||||
if (Submarine.MainSub != null)
|
||||
if (Submarine.MainSub != null && Submarine.Loaded.Contains(Submarine.MainSub))
|
||||
{
|
||||
Submarine.MainSub.FilePath = Path.Combine(tempPath, Submarine.MainSub.Name + ".sub");
|
||||
Submarine.MainSub.SaveAs(Submarine.MainSub.FilePath);
|
||||
@@ -77,7 +77,7 @@ namespace Barotrauma
|
||||
|
||||
XDocument doc = ToolBox.TryLoadXml(Path.Combine(TempPath, "gamesession.xml"));
|
||||
|
||||
string subPath = Path.Combine(TempPath, ToolBox.GetAttributeString(doc.Root, "submarine", ""));
|
||||
string subPath = Path.Combine(TempPath, ToolBox.GetAttributeString(doc.Root, "submarine", ""))+".sub";
|
||||
Submarine selectedMap = new Submarine(subPath, "");// Submarine.Load();
|
||||
GameMain.GameSession = new GameSession(selectedMap, fileName, doc);
|
||||
|
||||
@@ -285,19 +285,31 @@ namespace Barotrauma
|
||||
while (DecompressFile(sDir, zipStream, progress)) ;
|
||||
}
|
||||
|
||||
private static void ClearFolder(string FolderName)
|
||||
private static void ClearFolder(string FolderName, string[] ignoredFiles = null)
|
||||
{
|
||||
DirectoryInfo dir = new DirectoryInfo(FolderName);
|
||||
|
||||
foreach (FileInfo fi in dir.GetFiles())
|
||||
{
|
||||
bool ignore = false;
|
||||
foreach (string ignoredFile in ignoredFiles)
|
||||
{
|
||||
if (Path.GetFullPath(fi.FullName).Equals(Path.GetFullPath(ignoredFile)))
|
||||
{
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore) continue;
|
||||
|
||||
fi.IsReadOnly = false;
|
||||
fi.Delete();
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo di in dir.GetDirectories())
|
||||
{
|
||||
ClearFolder(di.FullName);
|
||||
ClearFolder(di.FullName, ignoredFiles);
|
||||
di.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Barotrauma
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static SpriteFont TryLoadFont(string file, Microsoft.Xna.Framework.Content.ContentManager contentManager)
|
||||
/*public static SpriteFont TryLoadFont(string file, Microsoft.Xna.Framework.Content.ContentManager contentManager)
|
||||
{
|
||||
SpriteFont font = null;
|
||||
try
|
||||
@@ -102,7 +102,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
}*/
|
||||
|
||||
public static object GetAttributeObject(XElement element, string name)
|
||||
{
|
||||
@@ -383,7 +383,7 @@ namespace Barotrauma
|
||||
return str.Substring(0, maxCharacters-3) + "...";
|
||||
}
|
||||
|
||||
public static string LimitString(string str, SpriteFont font, int maxWidth)
|
||||
public static string LimitString(string str, ScalableFont font, int maxWidth)
|
||||
{
|
||||
if (maxWidth <= 0 || string.IsNullOrWhiteSpace(str)) return "";
|
||||
|
||||
@@ -465,7 +465,7 @@ namespace Barotrauma
|
||||
return d[n, m];
|
||||
}
|
||||
|
||||
public static string WrapText(string text, float lineLength, SpriteFont font)
|
||||
public static string WrapText(string text, float lineLength, ScalableFont font) //TODO: could integrate this into the ScalableFont class directly
|
||||
{
|
||||
if (font.MeasureString(text).X < lineLength) return text;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user