This commit is contained in:
Joonas Rikkonen
2017-12-26 20:04:47 +02:00
72 changed files with 2763 additions and 2535 deletions
@@ -1,4 +1,4 @@
using Barotrauma.Networking;
using Barotrauma.Networking;
using Barotrauma.Particles;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
@@ -290,7 +290,15 @@ namespace Barotrauma
string name = Info.DisplayName;
if (controlled == null && name != Info.Name) name += " (Disguised)";
Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(name) * 0.5f / cam.Zoom;
Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(Info.Name) * 0.5f / cam.Zoom;
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
Vector2 viewportSize = new Vector2(cam.WorldView.Width, cam.WorldView.Height);
namePos.X -= cam.WorldView.X; namePos.Y += cam.WorldView.Y;
namePos *= screenSize / viewportSize;
namePos.X = (float)Math.Floor(namePos.X); namePos.Y = (float)Math.Floor(namePos.Y);
namePos *= viewportSize / screenSize;
namePos.X += cam.WorldView.X; namePos.Y -= cam.WorldView.Y;
Color nameColor = Color.White;
if (Controlled != null && TeamID != Controlled.TeamID)
@@ -145,6 +145,10 @@ namespace Barotrauma
float rotation = msg.ReadFloat();
ReadStatus(msg);
msg.ReadPadBits();
int index = 0;
if (GameMain.NetworkMember.Character == this)
{
@@ -193,9 +197,6 @@ namespace Barotrauma
IsRemotePlayer = ownerID > 0;
}
break;
case 2:
ReadStatus(msg);
break;
}
break;
@@ -28,7 +28,7 @@ namespace Barotrauma
static GUIFrame frame;
static GUIListBox listBox;
static GUITextBox textBox;
public static void Init(GameWindow window)
{
int x = 20, y = 20;
@@ -47,7 +47,7 @@ namespace Barotrauma
return true;
};
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
@@ -111,7 +111,7 @@ namespace Barotrauma
{
textBox.Text = AutoComplete(textBox.Text);
}
if (PlayerInput.KeyHit(Keys.Enter))
{
ExecuteCommand(textBox.Text);
@@ -164,7 +164,7 @@ namespace Barotrauma
{
listBox.children.RemoveRange(0, listBox.children.Count - MaxMessages);
}
Messages.Add(msg);
if (Messages.Count > MaxMessages)
{
@@ -190,10 +190,27 @@ namespace Barotrauma
private static void InitProjectSpecific()
{
commands.Add(new Command("autohull", "", (string[] args) =>
{
if (Screen.Selected != GameMain.SubEditorScreen) return;
if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap))
{
ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N",
(option) => {
if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull();
});
}
else
{
GameMain.SubEditorScreen.AutoHull();
}
}));
commands.Add(new Command("startclient", "", (string[] args) =>
{
if (args.Length == 0) return;
if (GameMain.Client == null)
{
GameMain.NetworkMember = new GameClient("Name");
@@ -227,7 +244,7 @@ namespace Barotrauma
}
GameMain.SubEditorScreen.Select();
}));
commands.Add(new Command("editcharacter", "", (string[] args) =>
{
GameMain.CharacterEditorScreen.Select();
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -427,12 +427,15 @@ namespace Barotrauma
ScreenOverlayColor, true);
}
if (GameMain.DebugDraw)
if (GameMain.ShowFPS || GameMain.DebugDraw)
{
DrawString(spriteBatch, new Vector2(10, 10),
DrawString(spriteBatch, new Vector2(10, 10),
"FPS: " + (int)GameMain.FrameCounter.AverageFramesPerSecond,
Color.White, Color.Black * 0.5f, 0, SmallFont);
}
if (GameMain.DebugDraw)
{
DrawString(spriteBatch, new Vector2(10, 25),
"Physics: " + GameMain.World.UpdateTime,
Color.White, Color.Black * 0.5f, 0, SmallFont);
@@ -1,4 +1,4 @@
using EventInput;
using EventInput;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -129,7 +129,38 @@ namespace Barotrauma
{
get { return new Vector2(rect.Center.X, rect.Center.Y); }
}
protected Rectangle ClampRect(Rectangle r)
{
if (parent == null) return r;
Rectangle parentRect = parent.ClampRect(parent.rect);
if (parentRect.Width <= 0 || parentRect.Height <= 0) return Rectangle.Empty;
if (parentRect.X > r.X)
{
int diff = parentRect.X - r.X;
r.X = parentRect.X;
r.Width -= diff;
}
if (parentRect.Y > r.Y)
{
int diff = parentRect.Y - r.Y;
r.Y = parentRect.Y;
r.Height -= diff;
}
if (parentRect.X + parentRect.Width < r.X + r.Width)
{
int diff = (r.X + r.Width) - (parentRect.X + parentRect.Width);
r.Width -= diff;
}
if (parentRect.Y + parentRect.Height < r.Y + r.Height)
{
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
r.Height -= diff;
}
if (r.Width <= 0 || r.Height <= 0) return Rectangle.Empty;
return r;
}
public virtual Rectangle Rect
{
get { return rect; }
@@ -162,7 +193,7 @@ namespace Barotrauma
public virtual Rectangle MouseRect
{
get { return CanBeFocused ? rect : Rectangle.Empty; }
get { return CanBeFocused ? ClampRect(rect) : Rectangle.Empty; }
}
public Dictionary<ComponentState, List<UISprite>> sprites;
@@ -283,7 +283,7 @@ namespace Barotrauma
{
get
{
return rect;
return ClampRect(rect);
}
}
@@ -54,7 +54,7 @@ namespace Barotrauma
public GUIMessage(string text, Color color, Vector2 position, float lifeTime, Alignment textAlignment, bool autoCenter)
{
coloredText = new ColoredText(text, color);
coloredText = new ColoredText(text, color, false);
pos = position;
this.lifeTime = lifeTime;
this.Alignment = textAlignment;
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
@@ -63,7 +63,7 @@ namespace Barotrauma
public override Rectangle MouseRect
{
get { return box.Rect; }
get { return ClampRect(box.Rect); }
}
public override ScalableFont Font
@@ -1,4 +1,4 @@
using Barotrauma.Networking;
using Barotrauma.Networking;
using Barotrauma.Particles;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
@@ -14,6 +14,7 @@ namespace Barotrauma
{
class GameMain : Game
{
public static bool ShowFPS = true;
public static bool DebugDraw;
public static FrameCounter FrameCounter;
@@ -470,7 +470,7 @@ namespace Barotrauma
}
else
{
body.FarseerBody.Enabled = false;
body.Enabled = false;
}
if ((newPosition - SimPosition).Length() > body.LinearVelocity.Length() * 2.0f)
@@ -1,4 +1,4 @@
using Barotrauma.Lights;
using Barotrauma.Lights;
using Barotrauma.Particles;
using Microsoft.Xna.Framework;
using System;
@@ -76,9 +76,9 @@ namespace Barotrauma
}
}
lightSource.Range = Math.Max(size.X, size.Y) * 10.0f / 2.0f;
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
lightSource.Position = position + Vector2.UnitY * 30.0f;
if (Math.Abs((lightSource.Range * 0.2f) - Math.Max(size.X, size.Y)) > 1.0f) lightSource.Range = Math.Max(size.X, size.Y) * 5.0f;
if (Vector2.DistanceSquared(lightSource.Position,position) > 5.0f) lightSource.Position = position + Vector2.UnitY * 30.0f;
if (size.X > 256.0f)
{
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
@@ -63,6 +63,7 @@ namespace Barotrauma
public void Update(float deltaTime)
{
dustOffset -= Vector2.UnitY * 10.0f * deltaTime;
while (dustOffset.Y <= -1024.0f) dustOffset.Y += 1024.0f;
}
public static VertexPositionColorTexture[] GetColoredVertices(VertexPositionTexture[] vertices, Color color)
@@ -108,7 +109,7 @@ namespace Barotrauma
Vector2 backgroundPos = cam.WorldViewCenter;
backgroundPos.Y = -backgroundPos.Y;
backgroundPos /= 20.0f;
backgroundPos *= 0.05f;
if (backgroundPos.Y < 1024)
{
@@ -130,35 +131,38 @@ namespace Barotrauma
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
SamplerState.LinearWrap, DepthStencilState.Default, null, null,
cam.Transform);
Vector2 origin = new Vector2(cam.WorldView.X, -cam.WorldView.Y);
Vector2 offset = -origin + dustOffset;
while (offset.X <= -1024.0f) offset.X += 1024.0f;
while (offset.X > 0.0f) offset.X -= 1024.0f;
while (offset.Y <= -1024.0f) offset.Y += 1024.0f;
while (offset.Y > 0.0f) offset.Y -= 1024.0f;
if (backgroundSpriteManager != null) backgroundSpriteManager.DrawSprites(spriteBatch, cam);
if (backgroundCreatureManager != null) backgroundCreatureManager.Draw(spriteBatch);
for (int i = 0; i < 4; i++)
{
float scale = 1.0f - i * 0.2f;
float recipScale = 1.0f / scale;
//alpha goes from 1.0 to 0.0 when scale is in the range of 0.2-0.1
float alpha = (cam.Zoom * scale) < 0.2f ? (cam.Zoom * scale - 0.1f) * 10.0f : 1.0f;
//alpha goes from 1.0 to 0.0 when scale is in the range of 0.5-0.25
float alpha = (cam.Zoom * scale) < 0.5f ? (cam.Zoom * scale - 0.25f) * 40.0f : 1.0f;
if (alpha <= 0.0f) continue;
Vector2 offset = (new Vector2(cam.WorldViewCenter.X, cam.WorldViewCenter.Y) + dustOffset) * scale;
Vector3 origin = new Vector3(cam.WorldView.Width, cam.WorldView.Height, 0.0f) * 0.5f;
Vector2 offsetS = offset * scale + new Vector2(cam.WorldView.Width, cam.WorldView.Height) * (1.0f - scale) * 0.5f - new Vector2(256.0f * i);
while (offsetS.X <= -1024.0f*scale) offsetS.X += 1024.0f*scale;
while (offsetS.X > 0.0f) offsetS.X -= 1024.0f*scale;
while (offsetS.Y <= -1024.0f*scale) offsetS.Y += 1024.0f*scale;
while (offsetS.Y > 0.0f) offsetS.Y -= 1024.0f*scale;
dustParticles.SourceRect = new Rectangle(
(int)((offset.X - origin.X + (i * 256)) / scale),
(int)((-offset.Y - origin.Y + (i * 256)) / scale),
(int)((cam.WorldView.Width) / scale),
(int)((cam.WorldView.Height) / scale));
spriteBatch.Draw(dustParticles.Texture,
new Vector2(cam.WorldViewCenter.X, -cam.WorldViewCenter.Y),
dustParticles.SourceRect, Color.White * alpha, 0.0f,
new Vector2(cam.WorldView.Width, cam.WorldView.Height) * 0.5f / scale, scale, SpriteEffects.None, 1.0f - scale);
Rectangle srcRect = new Rectangle(0, 0, 2048, 2048);
dustParticles.DrawTiled(spriteBatch, origin + offsetS, new Vector2(cam.WorldView.Width - offsetS.X, cam.WorldView.Height - offsetS.Y), Vector2.Zero, srcRect, Color.White * alpha, new Vector2(scale));
}
spriteBatch.End();
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -13,7 +13,11 @@ namespace Barotrauma
public VertexPositionTexture[] vertices = new VertexPositionTexture[DefaultBufferSize];
private Effect waterEffect;
public Effect waterEffect
{
get;
private set;
}
private BasicEffect basicEffect;
public int PositionInBuffer = 0;
@@ -93,7 +97,7 @@ namespace Barotrauma
basicEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
graphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, vertices.Length / 3);
}
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using System.Linq;
@@ -23,7 +23,17 @@ namespace Barotrauma.Lights
public Color AmbientLight;
RenderTarget2D lightMap, losTexture;
private float lightmapScale = 0.5f;
public RenderTarget2D lightMap
{
get;
private set;
}
public RenderTarget2D losTexture
{
get;
private set;
}
BasicEffect lightEffect;
@@ -36,8 +46,9 @@ namespace Barotrauma.Lights
public bool LightingEnabled = true;
public bool ObstructVision;
LightSource losSource;
private Texture2D visionCircle;
private Sprite visionCircle;
private Dictionary<Hull, Color> hullAmbientLights;
private Dictionary<Hull, Color> smoothedHullAmbientLights;
@@ -50,21 +61,26 @@ namespace Barotrauma.Lights
AmbientLight = new Color(20, 20, 20, 255);
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png");
//visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png");
visionCircle = new Sprite("Content/Lights/visioncircle.png", new Vector2(0.2f, 0.5f));
var pp = graphics.PresentationParameters;
lightMap = new RenderTarget2D(graphics,
GameMain.GraphicsWidth, GameMain.GraphicsHeight, false,
(int)(GameMain.GraphicsWidth*lightmapScale), (int)(GameMain.GraphicsHeight*lightmapScale), false,
pp.BackBufferFormat, pp.DepthStencilFormat, pp.MultiSampleCount,
RenderTargetUsage.DiscardContents);
losTexture = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
losTexture = new RenderTarget2D(graphics, (int)(GameMain.GraphicsWidth*lightmapScale), (int)(GameMain.GraphicsHeight*lightmapScale), false, SurfaceFormat.Alpha8, DepthFormat.None);
losSource = new LightSource(Vector2.Zero, GameMain.GraphicsWidth, Color.White, null, false);
losSource.texture = new Texture2D(graphics, 1, 1);
losSource.texture.SetData(new Color[] { Color.White });// fill the texture with white
if (lightEffect == null)
{
lightEffect = new BasicEffect(GameMain.Instance.GraphicsDevice);
lightEffect.VertexColorEnabled = false;
lightEffect.VertexColorEnabled = true;
lightEffect.TextureEnabled = true;
lightEffect.Texture = LightSource.LightTexture;
@@ -141,9 +157,9 @@ 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.CreateScale(new Vector3(lightmapScale, lightmapScale, 1.0f)));
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;
@@ -158,7 +174,7 @@ namespace Barotrauma.Lights
}
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
if (Character.Controlled != null)
@@ -201,56 +217,43 @@ namespace Barotrauma.Lights
public void UpdateObstructVision(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Vector2 lookAtPosition)
{
if (!LosEnabled && !ObstructVision) return;
if (!LosEnabled || ViewTarget == null) return;
graphics.SetRenderTarget(losTexture);
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, cam.Transform);
//--------------------------------------
graphics.Clear(Color.Black);
if (ObstructVision)
{
//graphics.Clear(Color.Black);
Vector2 diff = lookAtPosition - ViewTarget.WorldPosition;
diff.Y = -diff.Y;
float rotation = MathUtils.VectorToAngle(diff);
Vector2 scale = new Vector2(MathHelper.Clamp(diff.Length()/256.0f, 2.0f, 5.0f), 2.0f);
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
new Vector2(LightSource.LightTexture.Width*0.2f, LightSource.LightTexture.Height/2), scale, SpriteEffects.None, 0.0f);
Vector2 scale = new Vector2(MathHelper.Clamp(diff.Length() / 256.0f, 2.0f, 5.0f), 2.0f) * 0.3f;
visionCircle.size = new Vector2(visionCircle.SourceRect.Width * scale.X, visionCircle.SourceRect.Height * scale.Y);
losSource.overrideLightTexture = visionCircle;
losSource.Rotation = rotation;
}
else
{
graphics.Clear(Color.White);
losSource.overrideLightTexture = null;
}
spriteBatch.End();
graphics.BlendState = BlendState.Additive;
//--------------------------------------
Vector2 pos = ViewTarget.Position;
losSource.Position = pos;
losSource.NeedsRecalculation = true;
losSource.ParentSub = ViewTarget.Submarine;
if (LosEnabled && ViewTarget != null)
{
Vector2 pos = ViewTarget.WorldPosition;
Matrix transform = cam.ShaderTransform
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
losSource.Draw(spriteBatch, lightEffect, transform);
Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height);
graphics.BlendState = BlendState.AlphaBlend;
Matrix shadowTransform = cam.ShaderTransform
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
var convexHulls = ConvexHull.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine);
if (convexHulls != null)
{
foreach (ConvexHull convexHull in convexHulls)
{
if (!convexHull.Intersects(camView)) continue;
//if (!camView.Intersects(convexHull.BoundingBox)) continue;
convexHull.DrawShadows(graphics, cam, pos, shadowTransform);
}
}
}
graphics.SetRenderTarget(null);
}
@@ -338,22 +341,11 @@ namespace Barotrauma.Lights
{
if (!LightingEnabled) return;
spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.Multiplicative, null, null, null, effect);
spriteBatch.Draw(lightMap, Vector2.Zero, Color.White);
spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.Multiplicative, null, null, null, null);
spriteBatch.Draw(lightMap, new Rectangle(0,0,GameMain.GraphicsWidth,GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
}
public void DrawLOS(SpriteBatch spriteBatch, Effect effect,bool renderingBackground)
{
if (!LosEnabled || ViewTarget == null) return;
spriteBatch.Begin(SpriteSortMode.Deferred, renderingBackground ? CustomBlendStates.LOS : CustomBlendStates.Multiplicative, null, null, null, effect);
spriteBatch.Draw(losTexture, Vector2.Zero, Color.White);
spriteBatch.End();
if (!renderingBackground) ObstructVision = false;
}
public void ClearLights()
{
lights.Clear();
@@ -376,16 +368,10 @@ namespace Barotrauma.Lights
MultiplyWithAlpha = new BlendState();
MultiplyWithAlpha.ColorDestinationBlend = MultiplyWithAlpha.AlphaDestinationBlend = Blend.One;
MultiplyWithAlpha.ColorSourceBlend = MultiplyWithAlpha.AlphaSourceBlend = Blend.DestinationAlpha;
LOS = new BlendState();
LOS.ColorSourceBlend = LOS.AlphaSourceBlend = Blend.Zero;
LOS.ColorDestinationBlend = LOS.AlphaDestinationBlend = Blend.InverseSourceColor;
LOS.ColorBlendFunction = LOS.AlphaBlendFunction = BlendFunction.Add;
}
public static BlendState Multiplicative { get; private set; }
public static BlendState WriteToAlpha { get; private set; }
public static BlendState MultiplyWithAlpha { get; private set; }
public static BlendState LOS { get; private set; }
}
}
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
@@ -17,8 +17,8 @@ namespace Barotrauma.Lights
private Color color;
private float range;
private Sprite overrideLightTexture;
private Texture2D texture;
public Sprite overrideLightTexture;
public Texture2D texture;
public Sprite LightSprite;
@@ -140,7 +140,7 @@ namespace Barotrauma.Lights
}
}
public LightSource(Vector2 position, float range, Color color, Submarine submarine)
public LightSource(Vector2 position, float range, Color color, Submarine submarine, bool addLight=true)
{
hullsInRange = new List<ConvexHullList>();
@@ -156,7 +156,7 @@ namespace Barotrauma.Lights
diffToSub = new Dictionary<Submarine, Vector2>();
GameMain.LightManager.AddLight(this);
if (addLight) GameMain.LightManager.AddLight(this);
}
/*public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform)
@@ -322,6 +322,7 @@ namespace Barotrauma.Lights
hulls.AddRange(chList.List);
}
float bounds = range*2;
//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>();
@@ -336,6 +337,10 @@ namespace Barotrauma.Lights
{
points.Add(s.Start);
points.Add(s.End);
if (Math.Abs(s.Start.WorldPos.X - drawPos.X) > bounds) bounds = Math.Abs(s.Start.WorldPos.X - drawPos.X);
if (Math.Abs(s.Start.WorldPos.Y - drawPos.Y) > bounds) bounds = Math.Abs(s.Start.WorldPos.Y - drawPos.Y);
if (Math.Abs(s.End.WorldPos.X - drawPos.X) > bounds) bounds = Math.Abs(s.End.WorldPos.X - drawPos.X);
if (Math.Abs(s.End.WorldPos.Y - drawPos.Y) > bounds) bounds = Math.Abs(s.End.WorldPos.Y - drawPos.Y);
}
}
@@ -344,14 +349,21 @@ namespace Barotrauma.Lights
//(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))
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y + bounds)),
new SegmentPoint(new Vector2(drawPos.X + bounds, drawPos.Y - bounds)),
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y - bounds)),
new SegmentPoint(new Vector2(drawPos.X - bounds, drawPos.Y + bounds))
};
//points.Clear();
points.AddRange(boundaryCorners);
//visibleSegments.Clear();
for (int i=0;i<4;i++)
{
visibleSegments.Add(new Segment(boundaryCorners[i], boundaryCorners[(i + 1) % 4]));
}
var compareCCW = new CompareSegmentPointCW(drawPos);
try
{
@@ -368,14 +380,16 @@ namespace Barotrauma.Lights
}
List<Vector2> output = new List<Vector2>();
//List<Pair<int, Vector2>> preOutput = new List<Pair<int, 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)
if (Math.Abs(points[i].WorldPos.X - points[i + 1].WorldPos.X) < 6 &&
Math.Abs(points[i].WorldPos.Y - points[i + 1].WorldPos.Y) < 6)
{
points.RemoveAt(i + 1);
i--;
}
}
@@ -385,32 +399,52 @@ namespace Barotrauma.Lights
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);
Pair<int,Vector2> intersection1 = RayCast(drawPos, drawPos + dir * bounds * 2 - dirNormal, visibleSegments);
Pair<int,Vector2> intersection2 = RayCast(drawPos, drawPos + dir * bounds * 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))
if (intersection1.First < 0) return new List<Vector2>();
if (intersection2.First < 0) return new List<Vector2>();
Segment seg1 = visibleSegments[intersection1.First];
Segment seg2 = visibleSegments[intersection2.First];
bool isPoint1 = MathUtils.LineToPointDistance(seg1.Start.WorldPos, seg1.End.WorldPos, p.WorldPos) < 5.0f;
bool isPoint2 = MathUtils.LineToPointDistance(seg2.Start.WorldPos, seg2.End.WorldPos, p.WorldPos) < 5.0f;
//hit at the current segmentpoint -> place the segmentpoint into the list
if (isPoint1 && isPoint2)
{
output.Add(intersection1);
output.Add(p.WorldPos);
}
else
else if (intersection1.First != intersection2.First)
{
output.Add(intersection1);
output.Add(intersection2);
output.Add(isPoint1 ? p.WorldPos : intersection1.Second);
output.Add(isPoint2 ? p.WorldPos : intersection2.Second);
}
}
//remove points that are very close to each other
for (int i = 0; i < output.Count - 1; i++)
{
if (Math.Abs(output[i].X - output[i + 1].X) < 6 &&
Math.Abs(output[i].Y - output[i + 1].Y) < 6)
{
output.RemoveAt(i + 1);
i--;
}
}
return output;
}
private Vector2 RayCast(Vector2 rayStart, Vector2 rayEnd, List<Segment> segments)
private Pair<int,Vector2> RayCast(Vector2 rayStart, Vector2 rayEnd, List<Segment> segments)
{
float closestDist = 0.0f;
Vector2? closestIntersection = null;
foreach (Segment s in segments)
int segment = -1;
for (int i=0;i<segments.Count;i++)
{
Segment s = segments[i];
Vector2? intersection = MathUtils.GetAxisAlignedLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, s.IsHorizontal);
if (intersection != null)
@@ -420,16 +454,20 @@ namespace Barotrauma.Lights
{
closestDist = dist;
closestIntersection = intersection;
segment = i;
}
}
}
}
return closestIntersection == null ? rayEnd : (Vector2)closestIntersection;
Pair<int,Vector2> retVal = new Pair<int,Vector2>();
retVal.Second = closestIntersection == null ? rayEnd : (Vector2)closestIntersection;
retVal.First = segment;
return retVal;
}
private void CalculateLightVertices(List<Vector2> rayCastHits)
{
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
List<VertexPositionColorTexture> vertices = new List<VertexPositionColorTexture>();
Vector2 drawPos = position;
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
@@ -446,16 +484,19 @@ namespace Barotrauma.Lights
}
// 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));
vertices.Add(new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
Color.White,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)
for (int i = 0; i < rayCastHits.Count; i++)
{
Vector2 vertex = rayCastHits[i];
Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1];
Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0];
Vector2 rawDiff = vertex - drawPos;
Vector2 diff = rawDiff;
diff /= range*2.0f;
diff /= range * 2.0f;
if (overrideLightTexture != null)
{
Vector2 originDiff = diff;
@@ -467,22 +508,52 @@ namespace Barotrauma.Lights
diff += uvOffset;
}
vertices.Add(new VertexPositionTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
new Vector2(0.5f, 0.5f) + diff));
Vector2 nDiff1 = vertex - nextVertex;
float tx = nDiff1.X; nDiff1.X = -nDiff1.Y; nDiff1.Y = tx;
nDiff1 /= Math.Max(Math.Abs(nDiff1.X), Math.Abs(nDiff1.Y));
Vector2 nDiff2 = prevVertex - vertex;
tx = nDiff2.X; nDiff2.X = -nDiff2.Y; nDiff2.Y = tx;
nDiff2 /= Math.Max(Math.Abs(nDiff2.X),Math.Abs(nDiff2.Y));
Vector2 nDiff = nDiff1 + nDiff2;
nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y));
nDiff *= 50.0f;
if (Vector2.DistanceSquared(nDiff, rawDiff) > Vector2.DistanceSquared(-nDiff, rawDiff)) nDiff = -nDiff;
VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
Color.White * 0.0f, new Vector2(0.5f, 0.5f) + diff);
vertices.Add(new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
Color.White, new Vector2(0.5f, 0.5f) + diff));
vertices.Add(fadeVert);
}
// Compute the indices to form triangles
List<short> indices = new List<short>();
for (int i = 0; i < rayCastHits.Count - 1; i++)
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((short)((i*2 + 3) % vertices.Count));
indices.Add((short)((i*2 + 1) % vertices.Count));
indices.Add((short)((i*2 + 1) % vertices.Count));
indices.Add((short)((i*2 + 3) % vertices.Count));
indices.Add((short)((i*2 + 4) % vertices.Count));
indices.Add((short)((i*2 + 2) % vertices.Count));
indices.Add((short)((i*2 + 1) % vertices.Count));
indices.Add((short)((i*2 + 4) % vertices.Count));
}
indices.Add(0);
indices.Add((short)(1));
indices.Add((short)(vertices.Count - 1));
indices.Add((short)(vertices.Count - 2));
indices.Add((short)(1));
indices.Add((short)(vertices.Count-1));
indices.Add((short)(vertices.Count-2));
indices.Add((short)(1));
indices.Add((short)(2));
indices.Add((short)(vertices.Count-1));
vertexCount = vertices.Count;
indexCount = indices.Count;
@@ -491,19 +562,19 @@ namespace Barotrauma.Lights
//now we just create a buffer for 64 verts and make it larger if needed
if (lightVolumeBuffer == null)
{
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount*1.5)), BufferUsage.None);
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount*1.5)), BufferUsage.None);
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64*3, (int)(indexCount * 1.5)), BufferUsage.None);
}
else if (vertexCount > lightVolumeBuffer.VertexCount)
else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
{
lightVolumeBuffer.Dispose();
lightVolumeIndexBuffer.Dispose();
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, (int)(vertexCount*1.5), BufferUsage.None);
lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount*1.5), BufferUsage.None);
lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
}
lightVolumeBuffer.SetData<VertexPositionTexture>(vertices.ToArray());
lightVolumeBuffer.SetData<VertexPositionColorTexture>(vertices.ToArray());
lightVolumeIndexBuffer.SetData<short>(indices.ToArray());
}
@@ -562,7 +633,7 @@ namespace Barotrauma.Lights
}
else
{
lightEffect.Texture = LightTexture;
lightEffect.Texture = texture??LightTexture;
}
lightEffect.CurrentTechnique.Passes[0].Apply();
@@ -571,6 +642,7 @@ namespace Barotrauma.Lights
GameMain.Instance.GraphicsDevice.DrawIndexedPrimitives
(
//PrimitiveType.LineList, 0, 0, indexCount / 2
PrimitiveType.TriangleList, 0, 0, indexCount / 3
);
}
@@ -974,8 +974,14 @@ namespace Barotrauma.Networking
private void ReadIngameUpdate(NetIncomingMessage inc)
{
List<IServerSerializable> entities = new List<IServerSerializable>();
float sendingTime = inc.ReadFloat() - inc.SenderConnection.RemoteTimeOffset;
ServerNetObject? prevObjHeader = null;
long prevBitPos = 0;
long prevBytePos = 0;
ServerNetObject objHeader;
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
{
@@ -1004,15 +1010,51 @@ namespace Barotrauma.Networking
break;
case ServerNetObject.ENTITY_EVENT:
case ServerNetObject.ENTITY_EVENT_INITIAL:
entityEventManager.Read(objHeader, inc, sendingTime);
entityEventManager.Read(objHeader, inc, sendingTime, entities);
break;
case ServerNetObject.CHAT_MESSAGE:
ChatMessage.ClientRead(inc);
break;
default:
DebugConsole.ThrowError("Error while reading update from server (unknown object header \""+objHeader+"\"!)");
if (prevObjHeader != null)
{
DebugConsole.ThrowError("Previous object type: " + prevObjHeader.ToString());
}
else
{
DebugConsole.ThrowError("Error occurred on the very first object!");
}
DebugConsole.ThrowError("Previous object was " + (inc.Position - prevBitPos) + " bits long (" + (inc.PositionInBytes - prevBytePos) + " bytes)");
if (prevObjHeader == ServerNetObject.ENTITY_EVENT || prevObjHeader == ServerNetObject.ENTITY_EVENT_INITIAL)
{
foreach (IServerSerializable ent in entities)
{
if (ent == null)
{
DebugConsole.ThrowError(" - NULL");
continue;
}
Entity e = ent as Entity;
DebugConsole.ThrowError(" - "+e.ToString());
}
}
DebugConsole.ThrowError("Writing object data to \"crashreport_object.bin\", please send this file to us at http://github.com/Regalis11/Barotrauma/issues");
FileStream fl = File.Open("crashreport_object.bin", FileMode.Create);
BinaryWriter sw = new BinaryWriter(fl);
sw.Write(inc.Data, (int)prevBytePos, (int)(inc.LengthBytes - prevBytePos));
sw.Close();
fl.Close();
throw new Exception("Error while reading update from server: please send us \"crashreport_object.bin\"!");
break;
}
prevObjHeader = objHeader;
prevBitPos = inc.Position;
prevBytePos = inc.PositionInBytes;
}
}
@@ -100,7 +100,7 @@ namespace Barotrauma.Networking
/// <summary>
/// Read the events from the message, ignoring ones we've already received
/// </summary>
public void Read(ServerNetObject type, NetIncomingMessage msg, float sendingTime)
public void Read(ServerNetObject type, NetIncomingMessage msg, float sendingTime, List<IServerSerializable> entities)
{
UInt16 unreceivedEntityEventCount = 0;
@@ -128,6 +128,8 @@ namespace Barotrauma.Networking
firstNewID = null;
}
entities.Clear();
UInt16 firstEventID = msg.ReadUInt16();
int eventCount = msg.ReadByte();
@@ -146,6 +148,7 @@ namespace Barotrauma.Networking
byte msgLength = msg.ReadByte();
IServerSerializable entity = Entity.FindEntityByID(entityID) as IServerSerializable;
entities.Add(entity);
//skip the event if we've already received it or if the entity isn't found
if (thisEventID != (UInt16)(lastReceivedID + 1) || entity == null)
@@ -258,7 +258,7 @@ namespace Barotrauma.Particles
}
else
{
Hull newHull = Hull.FindHull(position);
Hull newHull = Hull.FindHull(position,currentHull);
if (newHull != currentHull)
{
currentHull = newHull;
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -14,7 +14,7 @@ namespace Barotrauma
readonly RenderTarget2D renderTargetBackground;
readonly RenderTarget2D renderTarget;
readonly RenderTarget2D renderTargetWater;
readonly RenderTarget2D renderTargetAir;
readonly RenderTarget2D renderTargetFinal;
private Effect damageEffect;
@@ -27,9 +27,9 @@ namespace Barotrauma
cam.Translate(new Vector2(-10.0f, 50.0f));
renderTargetBackground = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
renderTargetWater = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTargetAir = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTargetFinal = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None);
#if LINUX
@@ -97,7 +97,6 @@ namespace Barotrauma
public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch)
{
foreach (Submarine sub in Submarine.Loaded)
{
sub.UpdateTransform();
@@ -113,197 +112,137 @@ namespace Barotrauma
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
}
//----------------------------------------------------------------------------------------
//1. draw the background, characters and the parts of the submarine that are behind them
//----------------------------------------------------------------------------------------
graphics.SetRenderTarget(renderTargetBackground);
if (Level.Loaded == null)
{
graphics.Clear(new Color(11, 18, 26, 255));
}
else
{
//graphics.Clear(new Color(255, 255, 255, 255));
Level.Loaded.DrawBack(graphics, spriteBatch, cam);
}
//draw structures that are in water and not part of any sub (e.g. ruins)
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => s is Structure && s.Submarine == null);
spriteBatch.End();
//draw alpha blended particles that are in water and behind subs
//draw alpha blended particles that are in water and behind subs
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
//draw additive particles that are in water and behind subs
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
spriteBatch.End();
//draw submarine structures that are behind water
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => s is Structure && s.Submarine != null);
spriteBatch.End();
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
//draw additive particles that are in water and behind subs
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => s is Structure && ((Structure)s).ResizeVertical && ((Structure)s).ResizeHorizontal);
foreach (Structure s in Structure.WallList)
{
if ((s.ResizeVertical != s.ResizeHorizontal) && s.CastShadow)
{
GUI.DrawRectangle(spriteBatch, new Vector2(s.DrawPosition.X-s.WorldRect.Width/2,-s.DrawPosition.Y-s.WorldRect.Height/2), new Vector2(s.WorldRect.Width, s.WorldRect.Height), Color.Black, true);
}
}
spriteBatch.End();
graphics.SetRenderTarget(renderTarget);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => !(s is Structure));
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, null);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => !(s is Structure));
Submarine.DrawBack(spriteBatch, false, s => s is Structure && !(((Structure)s).ResizeVertical && ((Structure)s).ResizeHorizontal));
foreach (Character c in Character.CharacterList) c.Draw(spriteBatch);
spriteBatch.End();
//----------------------------------------------------------------------------------------
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
graphics.SetRenderTarget(renderTargetWater);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), waterColor);
spriteBatch.End();
//draw alpha blended particles that are inside a sub
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
//draw additive particles that are inside a sub
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
spriteBatch.End();
//----------------------------------------------------------------------------------------
//draw the rendertarget and particles that are only supposed to be drawn in air into renderTargetAir
graphics.SetRenderTarget(renderTargetAir);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
//draw alpha blended particles that are not in water
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
//draw additive particles that are not in water
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.DepthRead, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
spriteBatch.End();
if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
{
graphics.SetRenderTarget(renderTarget);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque, null, null, null, lightBlur.Effect);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
Submarine.DrawDamageable(spriteBatch, null, false);
Submarine.DrawFront(spriteBatch, false, s => s is Structure);
spriteBatch.End();
GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, true);
}
graphics.SetRenderTarget(null);
//----------------------------------------------------------------------------------------
//2. pass the renderTarget to the water shader to do the water effect
//----------------------------------------------------------------------------------------
Hull.renderer.RenderBack(spriteBatch, renderTargetWater);
Array.Clear(Hull.renderer.vertices, 0, Hull.renderer.vertices.Length);
Hull.renderer.PositionInBuffer = 0;
foreach (Hull hull in Hull.hullList)
{
hull.Render(graphics, cam);
}
Hull.renderer.Render(graphics, cam, renderTargetAir, Cam.ShaderTransform);
//----------------------------------------------------------------------------------------
//3. draw the sections of the map that are on top of the water
//----------------------------------------------------------------------------------------
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, null, null, cam.Transform);
Submarine.DrawFront(spriteBatch, false, null);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.NonPremultiplied, SamplerState.LinearWrap,
null, null,
damageEffect,
cam.Transform);
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
graphics.SetRenderTarget(renderTargetWater);
Submarine.DrawDamageable(spriteBatch, damageEffect, false);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), waterColor);
spriteBatch.End();
spriteBatch.End();
//draw alpha blended particles that are inside a sub
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect);
graphics.SetRenderTarget(renderTarget);
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
//draw alpha blended particles that are not in water
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
if (Level.Loaded != null) Level.Loaded.DrawFront(spriteBatch);
//draw additive particles that are not in water
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
spriteBatch.End();
foreach (Character c in Character.CharacterList) c.DrawFront(spriteBatch, cam);
graphics.SetRenderTarget(renderTargetFinal);
Hull.renderer.RenderBack(spriteBatch, renderTargetWater);
spriteBatch.End();
Array.Clear(Hull.renderer.vertices, 0, Hull.renderer.vertices.Length);
Hull.renderer.PositionInBuffer = 0;
foreach (Hull hull in Hull.hullList)
{
hull.Render(graphics, cam);
}
if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
{
GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, false);
Hull.renderer.Render(graphics, cam, renderTarget, Cam.ShaderTransform);
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.None, RasterizerState.CullNone, null);
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.NonPremultiplied, SamplerState.LinearWrap,
null, null,
damageEffect,
cam.Transform);
Submarine.DrawDamageable(spriteBatch, damageEffect, false);
spriteBatch.End();
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
Color.Lerp(GameMain.LightManager.AmbientLight * 0.5f, Color.Red, r));
//draw additive particles that are inside a sub
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
spriteBatch.End();
if (GameMain.LightManager.LightingEnabled)
{
spriteBatch.Begin(SpriteSortMode.Deferred, Lights.CustomBlendStates.Multiplicative, null, DepthStencilState.None, null, null, null);
spriteBatch.Draw(GameMain.LightManager.lightMap, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
}
spriteBatch.End();
}
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
foreach (Character c in Character.CharacterList) c.DrawFront(spriteBatch, cam);
if (Level.Loaded != null) Level.Loaded.DrawFront(spriteBatch);
spriteBatch.End();
graphics.SetRenderTarget(null);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, null, null, null);
if (GameMain.LightManager.LosEnabled && Character.Controlled!=null)
{
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
Color.Lerp(GameMain.LightManager.AmbientLight * 0.5f, Color.Red, r));
spriteBatch.End();
Hull.renderer.waterEffect.CurrentTechnique = Hull.renderer.waterEffect.Techniques["LosShader"];
Hull.renderer.waterEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.losTexture);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, DepthStencilState.None, null, Hull.renderer.waterEffect, null);
}
spriteBatch.Draw(renderTargetFinal, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
}
}
}
@@ -15,10 +15,10 @@ namespace Barotrauma
class Emitter : ISerializableEntity
{
public float EmitTimer;
[Editable(), Serialize("0.0,0.0", false)]
public Vector2 AngleRange { get; private set; }
[Editable(), Serialize("0.0,0.0", false)]
public Vector2 VelocityRange { get; private set; }
@@ -76,7 +76,7 @@ namespace Barotrauma
cam = new Camera();
guiRoot = new GUIFrame(Rectangle.Empty, null, null);
leftPanel = new GUIFrame(new Rectangle(0, 0, 150, GameMain.GraphicsHeight), "GUIFrameLeft", guiRoot);
leftPanel.Padding = new Vector4(10.0f, 20.0f, 10.0f, 20.0f);
@@ -150,7 +150,7 @@ namespace Barotrauma
}
private void SerializeAll()
{
{
XDocument doc = XMLExtensions.TryLoadXml(GameMain.ParticleManager.ConfigFile);
if (doc == null || doc.Root == null) return;
@@ -179,6 +179,7 @@ namespace Barotrauma
private void SerializeToClipboard(ParticlePrefab prefab)
{
#if WINDOWS
if (prefab == null) return;
XmlWriterSettings settings = new XmlWriterSettings();
@@ -197,6 +198,7 @@ namespace Barotrauma
}
Clipboard.SetText(sb.ToString());
#endif
}
public override void Update(double deltaTime)
@@ -901,7 +901,305 @@ namespace Barotrauma
previouslyUsedList.RemoveChild(textBlock);
previouslyUsedList.children.Insert(0, textBlock);
}
public void AutoHull()
{
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
{
MapEntity h = MapEntity.mapEntityList[i];
if (h is Hull || h is Gap)
{
h.Remove();
i--;
}
}
List<Vector2> wallPoints = new List<Vector2>();
Vector2 min = Vector2.Zero;
Vector2 max = Vector2.Zero;
List<MapEntity> mapEntityList = new List<MapEntity>();
foreach (MapEntity e in MapEntity.mapEntityList)
{
if (e is Item)
{
Item it = e as Item;
Door door = it.GetComponent<Door>();
if (door != null)
{
int halfW = e.WorldRect.Width / 2;
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y + e.WorldRect.Height));
mapEntityList.Add(it);
}
continue;
}
if (!(e is Structure)) continue;
Structure s = e as Structure;
if (!s.HasBody) continue;
mapEntityList.Add(e);
if (e.Rect.Width > e.Rect.Height)
{
int halfH = e.WorldRect.Height / 2;
wallPoints.Add(new Vector2(e.WorldRect.X, -e.WorldRect.Y + halfH));
wallPoints.Add(new Vector2(e.WorldRect.X + e.WorldRect.Width, -e.WorldRect.Y + halfH));
}
else
{
int halfW = e.WorldRect.Width / 2;
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y));
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y + e.WorldRect.Height));
}
}
min = wallPoints[0];
max = wallPoints[0];
for (int i = 0; i < wallPoints.Count; i++)
{
min.X = Math.Min(min.X, wallPoints[i].X);
min.Y = Math.Min(min.Y, wallPoints[i].Y);
max.X = Math.Max(max.X, wallPoints[i].X);
max.Y = Math.Max(max.Y, wallPoints[i].Y);
}
List<Rectangle> hullRects = new List<Rectangle>();
hullRects.Add(new Rectangle((int)min.X, (int)min.Y, (int)(max.X - min.X), (int)(max.Y - min.Y)));
foreach (Vector2 point in wallPoints)
{
MathUtils.SplitRectanglesHorizontal(hullRects, point);
MathUtils.SplitRectanglesVertical(hullRects, point);
}
hullRects.Sort((a, b) =>
{
if (a.Y < b.Y) return -1;
if (a.Y > b.Y) return 1;
if (a.X < b.X) return -1;
if (a.X > b.X) return 1;
return 0;
});
for (int i = 0; i < hullRects.Count - 1; i++)
{
Rectangle rect = hullRects[i];
if (hullRects[i + 1].Y > rect.Y) continue;
Vector2 hullRPoint = new Vector2(rect.X + rect.Width - 8, rect.Y + rect.Height / 2);
Vector2 hullLPoint = new Vector2(rect.X, rect.Y + rect.Height / 2);
MapEntity container = null;
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
entRect.Y = -entRect.Y;
if (entRect.Contains(hullRPoint))
{
if (!entRect.Contains(hullLPoint)) container = e;
break;
}
}
if (container == null)
{
rect.Width += hullRects[i + 1].Width;
hullRects[i] = rect;
hullRects.RemoveAt(i + 1);
i--;
}
}
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
if (entRect.Width < entRect.Height) continue;
entRect.Y = -entRect.Y - 16;
for (int i = 0; i < hullRects.Count; i++)
{
Rectangle hullRect = hullRects[i];
if (entRect.Intersects(hullRect))
{
if (hullRect.Y < entRect.Y)
{
hullRect.Height = Math.Max((entRect.Y + 16 + entRect.Height / 2) - hullRect.Y, hullRect.Height);
hullRects[i] = hullRect;
}
else if (hullRect.Y + hullRect.Height <= entRect.Y + 16 + entRect.Height)
{
hullRects.RemoveAt(i);
i--;
}
}
}
}
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
if (entRect.Width < entRect.Height) continue;
entRect.Y = -entRect.Y;
for (int i = 0; i < hullRects.Count; i++)
{
Rectangle hullRect = hullRects[i];
if (entRect.Intersects(hullRect))
{
if (hullRect.Y >= entRect.Y - 8 && hullRect.Y + hullRect.Height <= entRect.Y + entRect.Height + 8)
{
hullRects.RemoveAt(i);
i--;
}
}
}
}
for (int i = 0; i < hullRects.Count;)
{
Rectangle hullRect = hullRects[i];
Vector2 point = new Vector2(hullRect.X+2, hullRect.Y+hullRect.Height/2);
MapEntity container = null;
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
entRect.Y = -entRect.Y;
if (entRect.Contains(point))
{
container = e;
break;
}
}
if (container == null)
{
hullRects.RemoveAt(i);
continue;
}
while (hullRects[i].Y <= hullRect.Y)
{
i++;
if (i >= hullRects.Count) break;
}
}
for (int i = hullRects.Count-1; i >= 0;)
{
Rectangle hullRect = hullRects[i];
Vector2 point = new Vector2(hullRect.X+hullRect.Width-2, hullRect.Y+hullRect.Height/2);
MapEntity container = null;
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
entRect.Y = -entRect.Y;
if (entRect.Contains(point))
{
container = e;
break;
}
}
if (container == null)
{
hullRects.RemoveAt(i); i--;
continue;
}
while (hullRects[i].Y >= hullRect.Y)
{
i--;
if (i < 0) break;
}
}
hullRects.Sort((a, b) =>
{
if (a.X < b.X) return -1;
if (a.X > b.X) return 1;
if (a.Y < b.Y) return -1;
if (a.Y > b.Y) return 1;
return 0;
});
for (int i = 0; i < hullRects.Count - 1; i++)
{
Rectangle rect = hullRects[i];
if (hullRects[i + 1].Width != rect.Width) continue;
if (hullRects[i + 1].X > rect.X) continue;
Vector2 hullBPoint = new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height - 8);
Vector2 hullUPoint = new Vector2(rect.X + rect.Width / 2, rect.Y);
MapEntity container = null;
foreach (MapEntity e in mapEntityList)
{
Rectangle entRect = e.WorldRect;
entRect.Y = -entRect.Y;
if (entRect.Contains(hullBPoint))
{
if (!entRect.Contains(hullUPoint)) container = e;
break;
}
}
if (container == null)
{
rect.Height += hullRects[i + 1].Height;
hullRects[i] = rect;
hullRects.RemoveAt(i + 1);
i--;
}
}
for (int i = 0; i < hullRects.Count;i++)
{
Rectangle rect = hullRects[i];
rect.Y -= 16;
rect.Height += 32;
hullRects[i] = rect;
}
hullRects.Sort((a, b) =>
{
if (a.Y < b.Y) return -1;
if (a.Y > b.Y) return 1;
if (a.X < b.X) return -1;
if (a.X > b.X) return 1;
return 0;
});
for (int i = 0; i < hullRects.Count; i++)
{
for (int j = i+1; j < hullRects.Count; j++)
{
if (hullRects[j].Y <= hullRects[i].Y) continue;
if (hullRects[j].Intersects(hullRects[i]))
{
Rectangle rect = hullRects[i];
rect.Height = hullRects[j].Y - rect.Y;
hullRects[i] = rect;
break;
}
}
}
foreach (Rectangle rect in hullRects)
{
Rectangle hullRect = rect;
hullRect.Y = -hullRect.Y;
Hull newHull = new Hull(MapEntityPrefab.Find("Hull"),
hullRect,
Submarine.MainSub);
}
foreach (MapEntity e in mapEntityList)
{
if (!(e is Structure)) continue;
if (!(e as Structure).IsPlatform) continue;
Rectangle gapRect = e.WorldRect;
gapRect.Y -= 8;
gapRect.Height = 16;
Gap newGap = new Gap(MapEntityPrefab.Find("Gap"),
gapRect);
}
}
public override void AddToGUIUpdateList()
{
if (tutorial != null) tutorial.AddToGUIUpdateList();
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
@@ -186,18 +186,23 @@ namespace Barotrauma
public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color)
{
DrawTiled(spriteBatch, pos, targetSize, startOffset, sourceRect, color);
DrawTiled(spriteBatch, pos, targetSize, startOffset, sourceRect, color, Vector2.One);
}
public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Rectangle sourceRect, Color color)
{
DrawTiled(spriteBatch, pos, targetSize, startOffset, sourceRect, color, Vector2.One);
}
public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Rectangle sourceRect, Color color, Vector2 scale)
{
//pos.X = (int)pos.X;
//pos.Y = (int)pos.Y;
//how many times the texture needs to be drawn on the x-axis
int xTiles = (int)Math.Ceiling((targetSize.X + startOffset.X) / sourceRect.Width);
int xTiles = (int)Math.Ceiling((targetSize.X + startOffset.X) / (sourceRect.Width*scale.X));
//how many times the texture needs to be drawn on the y-axis
int yTiles = (int)Math.Ceiling((targetSize.Y + startOffset.Y) / sourceRect.Height);
int yTiles = (int)Math.Ceiling((targetSize.Y + startOffset.Y) / (sourceRect.Height*scale.Y));
Vector2 position = pos - startOffset;
Rectangle drawRect = sourceRect;
@@ -211,11 +216,11 @@ namespace Barotrauma
if (x == xTiles - 1)
{
drawRect.Width -= (int)((position.X + sourceRect.Width) - (pos.X + targetSize.X));
drawRect.Width -= (int)((position.X + sourceRect.Width*scale.X) - (pos.X + targetSize.X));
}
else
{
drawRect.Width = sourceRect.Width;
drawRect.Width = (int)(sourceRect.Width*scale.X);
}
if (position.X < pos.X)
@@ -234,11 +239,11 @@ namespace Barotrauma
if (y == yTiles - 1)
{
drawRect.Height -= (int)((position.Y + sourceRect.Height) - (pos.Y + targetSize.Y));
drawRect.Height -= (int)((position.Y + sourceRect.Height*scale.Y) - (pos.Y + targetSize.Y));
}
else
{
drawRect.Height = sourceRect.Height;
drawRect.Height = (int)(sourceRect.Height*scale.Y);
}
if (position.Y < pos.Y)
@@ -252,10 +257,10 @@ namespace Barotrauma
spriteBatch.Draw(texture, position,
drawRect, color, rotation, Vector2.Zero, 1.0f, effects, depth);
position.Y += sourceRect.Height;
position.Y += sourceRect.Height*scale.Y;
}
position.X += sourceRect.Width;
position.X += sourceRect.Width*scale.X;
}
}
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using Color = Microsoft.Xna.Framework.Color;
@@ -44,7 +44,7 @@ namespace Barotrauma
try
{
using (Stream fileStream = File.OpenRead(path))
using (Stream fileStream = File.OpenRead(path))
{
var texture = Texture2D.FromStream(_graphicsDevice, fileStream);
texture = PreMultiplyAlpha(texture);