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:
Regalis
2017-03-11 13:24:09 +02:00
264 changed files with 31522 additions and 704 deletions
+18 -9
View File
@@ -111,6 +111,7 @@
<Compile Include="Source\Events\Missions\MonsterMission.cs" />
<Compile Include="Source\Events\Missions\SalvageMission.cs" />
<Compile Include="Source\Events\ArtifactEvent.cs" />
<Compile Include="Source\Fonts\ScalableFont.cs" />
<Compile Include="Source\GameSession\CargoManager.cs" />
<Compile Include="Source\GameSession\GameModes\GameModePreset.cs" />
<Compile Include="Source\GameSession\GameModes\MissionMode.cs" />
@@ -176,6 +177,7 @@
<Compile Include="Source\Networking\Voting.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Timing.cs" />
<Compile Include="Source\Utils\Homoglyphs.cs" />
<Compile Include="Source\Utils\MTRandom.cs" />
<Compile Include="Source\Utils\Rand.cs" />
<Compile Include="Source\Events\PropertyTask.cs" />
@@ -1061,6 +1063,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</Content>
<Content Include="freetype6.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Icon.ico" />
<Content Include="Mods\info.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -1236,6 +1241,9 @@
<None Include="Content\Characters\Watcher\watch6.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Code Pro Bold.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Content.mgcb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -1245,6 +1253,12 @@
<None Include="Content\effects.mgfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Exo2-Light.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Exo2-Medium.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Items\Artifacts\aliendoor.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -1359,15 +1373,9 @@
<None Include="Content\Items\Weapons\stungrenade.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\LargeFont.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Map\TutorialSub.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\SmallFont.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Ambient\Ambient1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -1641,9 +1649,6 @@
<None Include="Content\Sounds\Water\WaterAmbience2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\SpriteFont1.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\step.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -1680,6 +1685,10 @@
<Project>{49ba1c69-6104-41ac-a5d8-b54fa9f696e8}</Project>
<Name>Lidgren.Network</Name>
</ProjectReference>
<ProjectReference Include="..\SharpFont\Source\SharpFont\SharpFont.csproj">
<Project>{c293db32-fa42-486d-b128-5a12522fae4e}</Project>
<Name>SharpFont</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -82,5 +82,21 @@
<overridecommonness commonness="10" leveltype="Pillars" />
<overridecommonness commonness="10" leveltype="Slabs" />
<Sprite texture="Content/BackgroundSprites/vegetation5.png" sourcerect="580,151,444,873" origin="0.3,0.95"/>
</branch>
</branch>
<icechunk minsize="5" maxsize="8" randomrotation="-180,180" swingamount="0" commonness="10" depthrange="100,2000">
<Sprite texture="Content/BackgroundSprites/ice.png" sourcerect="0,0,668,523" origin="0.5,0.5"/>
</icechunk>
<icechunk minsize="5" maxsize="8" randomrotation="-180,180" swingamount="0" commonness="10" depthrange="100,2000">
<Sprite texture="Content/BackgroundSprites/ice.png" sourcerect="669,0,335,513" origin="0.5,0.5"/>
</icechunk>
<icechunk minsize="5" maxsize="8" randomrotation="-180,180" swingamount="0" commonness="10" depthrange="100,2000">
<Sprite texture="Content/BackgroundSprites/ice.png" sourcerect="0,523,331,501" origin="0.5,0.5"/>
</icechunk>
<icechunk minsize="5" maxsize="8" randomrotation="-180,180" swingamount="0" commonness="10" depthrange="100,2000">
<Sprite texture="Content/BackgroundSprites/ice.png" sourcerect="702,513,322,511" origin="0.5,0.5"/>
</icechunk>
</backgroundsprites>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

After

Width:  |  Height:  |  Size: 917 KiB

Binary file not shown.
-18
View File
@@ -13,24 +13,6 @@
#---------------------------------- Content ---------------------------------#
#begin LargeFont.spritefont
/importer:FontDescriptionImporter
/processor:FontDescriptionProcessor
/processorParam:TextureFormat=Color
/build:LargeFont.spritefont
#begin SmallFont.spritefont
/importer:FontDescriptionImporter
/processor:FontDescriptionProcessor
/processorParam:TextureFormat=Color
/build:SmallFont.spritefont
#begin SpriteFont1.spritefont
/importer:FontDescriptionImporter
/processor:FontDescriptionProcessor
/processorParam:TextureFormat=Color
/build:SpriteFont1.spritefont
#begin watershader.fx
/importer:EffectImporter
/processor:EffectProcessor
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -34,7 +34,7 @@
<Sprite texture ="door.png" sourcerect="1,0,48,208" depth="0.01" origin="0.5,0.5"/>
<Door window="0,0,10,107" canbeselected="true">
<Door window="0,-32,10,75" canbeselected="true">
<Sprite texture ="door.png" sourcerect="56,0,19,208" depth="0.05" origin="0.5,0.0"/>
<WeldedSprite texture ="door.png" sourcerect="9,0,32,188" depth="0.0" origin="0.5,0.5"/>
<sound file="door.ogg" type="OnUse" range="500.0"/>
-42
View File
@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<FontName>Code Pro Bold</FontName>
<Size>16</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Bold</Style>
<DefaultCharacter>_</DefaultCharacter>
<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#1200;</End>
</CharacterRegion>
<CharacterRegion>
<Start>&#192;</Start>
<End>&#601;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
Binary file not shown.
-42
View File
@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<FontName>Exo Light</FontName>
<Size>9</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Regular</Style>
<DefaultCharacter>_</DefaultCharacter>
<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#1200;</End>
</CharacterRegion>
<CharacterRegion>
<Start>&#192;</Start>
<End>&#601;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
Binary file not shown.
-65
View File
@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<!--
Modify this string to change the font that will be imported.
-->
<FontName>Exo Medium</FontName>
<!--
Size is a float value, measured in points. Modify this value to change
the size of the font.
-->
<Size>10</Size>
<!--
Spacing is a float value, measured in pixels. Modify this value to change
the amount of spacing in between characters.
-->
<Spacing>0</Spacing>
<!--
UseKerning controls the layout of the font. If this value is true, kerning information
will be used when placing characters.
-->
<UseKerning>true</UseKerning>
<!--
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
and "Bold, Italic", and are case sensitive.
-->
<Style>Regular</Style>
<!--
If you uncomment this line, the default character will be substituted if you draw
or measure text that contains characters which were not included in the font.
-->
<DefaultCharacter>_</DefaultCharacter>
<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#1200;</End>
</CharacterRegion>
<CharacterRegion>
<Start>&#192;</Start>
<End>&#601;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
Binary file not shown.
@@ -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);
+6 -4
View File
@@ -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);
+2 -2
View File
@@ -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
View 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;
}
}
}
+21 -12
View File
@@ -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);
+1 -1
View File
@@ -84,7 +84,7 @@ namespace Barotrauma
set { textBlock.TextColor = value; }
}
public override SpriteFont Font
public override ScalableFont Font
{
get
{
+46 -8
View File
@@ -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);
+5 -3
View File
@@ -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);
}
+11
View File
@@ -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);
+7 -7
View File
@@ -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),
+6 -4
View File
@@ -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);
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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);
}
+10 -1
View File
@@ -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;
+1 -1
View File
@@ -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()
+1 -1
View File
@@ -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)),
+10 -1
View File
@@ -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 =
+2 -2
View File
@@ -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)
+242 -78
View File
@@ -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
}
}
}
}
}
+28 -39
View File
@@ -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)
{
+352 -122
View File
@@ -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);
}
}
+1 -1
View File
@@ -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);
}
}
+36 -6
View File
@@ -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;
+2 -2
View File
@@ -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;
+2 -3
View File
@@ -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
+7 -7
View File
@@ -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);
}
}
+38 -36
View File
@@ -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;
+4 -4
View File
@@ -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;
+3 -3
View File
@@ -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);
}
+37 -18
View File
@@ -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);
-21
View File
@@ -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);
}
}
}
}
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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();
}
+9 -2
View File
@@ -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;
}
+20
View File
@@ -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;
+4
View File
@@ -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();
}
+6 -24
View File
@@ -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()
+44 -4
View File
@@ -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);
File diff suppressed because it is too large Load Diff
+111 -42
View File
@@ -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);
}
}
}
+17 -5
View File
@@ -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();
}
}
+4 -4
View File
@@ -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;
+35
View File
@@ -1,3 +1,38 @@
---------------------------------------------------------------------------------------------------------
v0.5.4.5
---------------------------------------------------------------------------------------------------------
- optimized light rendering
- switched fonts again, now to ones that support the cyrillic alphabet
- special symbols are allowed in player names again (unless there's already a player on the server
with a visually identical name)
- fixed monsters not appearing in the position indicated by the sonar in monster missions (or being desynced
whenever they did)
- fixed the game process staying active in the background after a crash
- players can't use headsets that are in the inventory
- the warning message about unlinked vents is only shown once when saving a sub (not for each vent)
- another attempt to fix AddToGUIUpdateList and SetTransformIgnoreContacts errors
---------------------------------------------------------------------------------------------------------
v0.5.4.4
---------------------------------------------------------------------------------------------------------
- new fonts
- spectators see indicators for both subs during combat missions
- fixed saves becoming corrupted if the player saves and quits in the "map view"
- fixed "OpenAL not found" errors if trying to run the game with no enabled audio devices
- fixed OpenAL errors when quitting a round
- fixed unconscious/dead characters falling through floors
- the server list accepts multiple servers from the same IP (assuming they're running on different ports)
- fixed autorestart and the start button getting stuck if the server fails to load the respawn shuttle
- fixed server failing to start a round if the cargo spawnpoint has been placed outside the submarine
- fixed AddToGUIUpdateList errors
- fixed SetTransformIgnoreContacts errors
- tickboxes work again in the item UIs in wiring/character mode
- fixed characters standing in an incorrect position when using railgun controllers in a mirrored sub
- spawning a scorpion (an old placeholder enemy) doesn't crash the game anymore
- submarine editor shows a warning if there are structures/items way outside the sub
---------------------------------------------------------------------------------------------------------
v0.5.4.3
---------------------------------------------------------------------------------------------------------
Binary file not shown.