Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -1,5 +1,4 @@
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
@@ -13,6 +12,7 @@ namespace Barotrauma.Lights
public readonly Submarine Submarine;
public HashSet<ConvexHull> IsHidden = new HashSet<ConvexHull>();
public HashSet<ConvexHull> HasBeenVisible = new HashSet<ConvexHull>();
public readonly List<ConvexHull> List = new List<ConvexHull>();
public ConvexHullList(Submarine submarine)
@@ -443,10 +443,10 @@ namespace Barotrauma.Lights
public bool Intersects(Rectangle rect)
{
if (!Enabled) return false;
if (!Enabled) { return false; }
Rectangle transformedBounds = BoundingBox;
if (ParentEntity != null && ParentEntity.Submarine != null)
if (ParentEntity is { Submarine: not null })
{
transformedBounds.X += (int)ParentEntity.Submarine.Position.X;
transformedBounds.Y += (int)ParentEntity.Submarine.Position.Y;
@@ -174,7 +174,7 @@ namespace Barotrauma.Lights
}
private readonly List<LightSource> activeLights = new List<LightSource>(capacity: 100);
private readonly List<LightSource> activeLightsWithLightVolume = new List<LightSource>(capacity: 100);
private readonly List<LightSource> activeShadowCastingLights = new List<LightSource>(capacity: 100);
public static int ActiveLightCount { get; private set; }
@@ -243,6 +243,7 @@ namespace Barotrauma.Lights
}
}
/// <param name="backgroundObstructor">A render target that contains the structures that should obstruct lights in the background. If not given, damageable walls and hulls are rendered to obstruct the background lights.</param>
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
{
if (!LightingEnabled) { return; }
@@ -273,13 +274,13 @@ namespace Barotrauma.Lights
{
light.ParentBody.UpdateDrawPosition();
Vector2 pos = light.ParentBody.DrawPosition;
Vector2 pos = light.ParentBody.DrawPosition + light.OffsetFromBody;
if (light.ParentSub != null) { pos -= light.ParentSub.DrawPosition; }
light.Position = pos;
}
//above the top boundary of the level (in an inactive respawn shuttle?)
if (Level.Loaded != null && light.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (Level.IsPositionAboveLevel(light.WorldPosition)) { continue; }
float range = light.LightSourceParams.TextureRange;
if (light.LightSprite != null)
@@ -315,19 +316,20 @@ namespace Barotrauma.Lights
}
//find the lights with an active light volume
activeLightsWithLightVolume.Clear();
activeShadowCastingLights.Clear();
foreach (var activeLight in activeLights)
{
if (!activeLight.CastShadows) { continue; }
if (activeLight.Range < 1.0f || activeLight.Color.A < 1 || activeLight.CurrentBrightness <= 0.0f) { continue; }
activeLightsWithLightVolume.Add(activeLight);
activeShadowCastingLights.Add(activeLight);
}
//remove some lights with a light volume if there's too many of them
if (activeLightsWithLightVolume.Count > GameSettings.CurrentConfig.Graphics.VisibleLightLimit && Screen.Selected is { IsEditor: false })
if (activeShadowCastingLights.Count > GameSettings.CurrentConfig.Graphics.VisibleLightLimit && Screen.Selected is { IsEditor: false })
{
for (int i = GameSettings.CurrentConfig.Graphics.VisibleLightLimit; i < activeLightsWithLightVolume.Count; i++)
for (int i = GameSettings.CurrentConfig.Graphics.VisibleLightLimit; i < activeShadowCastingLights.Count; i++)
{
activeLights.Remove(activeLightsWithLightVolume[i]);
activeLights.Remove(activeShadowCastingLights[i]);
}
}
activeLights.Sort((l1, l2) => l1.LastRecalculationTime.CompareTo(l2.LastRecalculationTime));
@@ -410,11 +412,21 @@ namespace Barotrauma.Lights
}
spriteBatch.End();
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
spriteBatch.End();
if (backgroundObstructor != null)
{
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: Matrix.Identity, effect: GameMain.GameScreen.DamageEffect);
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
spriteBatch.End();
}
else
{
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
spriteBatch.End();
}
graphics.BlendState = BlendState.Additive;
@@ -679,11 +691,14 @@ namespace Barotrauma.Lights
}
return visibleHulls;
}
private static readonly List<VertexPositionColor> ShadowVertices = new List<VertexPositionColor>(500);
private static readonly List<VertexPositionTexture> PenumbraVertices = new List<VertexPositionTexture>(500);
public void UpdateObstructVision(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Vector2 lookAtPosition)
{
if ((!LosEnabled || LosMode == LosMode.None) && ObstructVisionAmount <= 0.0f) { return; }
if (ViewTarget == null) return;
if (ViewTarget == null) { return; }
graphics.SetRenderTarget(LosTexture);
@@ -766,11 +781,11 @@ namespace Barotrauma.Lights
if (convexHulls != null)
{
List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>();
List<VertexPositionTexture> penumbraVerts = new List<VertexPositionTexture>();
ShadowVertices.Clear();
PenumbraVertices.Clear();
foreach (ConvexHull convexHull in convexHulls)
{
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
if (!convexHull.Intersects(camView)) { continue; }
Vector2 relativeViewPos = pos;
if (convexHull.ParentEntity?.Submarine != null)
@@ -782,26 +797,26 @@ namespace Barotrauma.Lights
for (int i = 0; i < convexHull.ShadowVertexCount; i++)
{
shadowVerts.Add(convexHull.ShadowVertices[i]);
ShadowVertices.Add(convexHull.ShadowVertices[i]);
}
for (int i = 0; i < convexHull.PenumbraVertexCount; i++)
{
penumbraVerts.Add(convexHull.PenumbraVertices[i]);
PenumbraVertices.Add(convexHull.PenumbraVertices[i]);
}
}
if (shadowVerts.Count > 0)
if (ShadowVertices.Count > 0)
{
ConvexHull.shadowEffect.World = shadowTransform;
ConvexHull.shadowEffect.CurrentTechnique.Passes[0].Apply();
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, shadowVerts.ToArray(), 0, shadowVerts.Count / 3, VertexPositionColor.VertexDeclaration);
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, ShadowVertices.ToArray(), 0, ShadowVertices.Count / 3, VertexPositionColor.VertexDeclaration);
if (penumbraVerts.Count > 0)
if (PenumbraVertices.Count > 0)
{
ConvexHull.penumbraEffect.World = shadowTransform;
ConvexHull.penumbraEffect.CurrentTechnique.Passes[0].Apply();
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, penumbraVerts.ToArray(), 0, penumbraVerts.Count / 3, VertexPositionTexture.VertexDeclaration);
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, PenumbraVertices.ToArray(), 0, PenumbraVertices.Count / 3, VertexPositionTexture.VertexDeclaration);
}
}
}
@@ -827,7 +842,7 @@ namespace Barotrauma.Lights
public void ClearLights()
{
activeLights.Clear();
activeLightsWithLightVolume.Clear();
activeShadowCastingLights.Clear();
lights.Clear();
}
}
@@ -1,4 +1,4 @@
using Barotrauma.Extensions;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
@@ -245,7 +245,7 @@ namespace Barotrauma.Lights
}
set
{
if (!needsRecalculation && value)
if (value)
{
foreach (ConvexHullList chList in convexHullsInRange)
{
@@ -450,6 +450,8 @@ namespace Barotrauma.Lights
set;
}
public Vector2 OffsetFromBody;
public DeformableSprite DeformableLightSprite
{
get;
@@ -550,7 +552,6 @@ namespace Barotrauma.Lights
chList.List.Clear();
foreach (var convexHull in fullChList.List)
{
if (!convexHull.Enabled) { continue; }
if (!MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, convexHull.BoundingBox)) { continue; }
if (lightSourceParams.Directional)
{
@@ -562,9 +563,9 @@ namespace Barotrauma.Lights
// center is in the opposite direction from the ray (cheapest check first)
if (Vector2.Dot(ray, convexHull.BoundingBox.Center.ToVector2() - lightPos) <= 0 &&
/*ray doesn't hit the convex hull*/
!MathUtils.GetLineRectangleIntersection(lightPos, lightPos + ray, bounds, out _) &&
!MathUtils.GetLineWorldRectangleIntersection(lightPos, lightPos + ray, bounds, out _) &&
/*normal vectors of the ray don't hit the convex hull */
!MathUtils.GetLineRectangleIntersection(lightPos + normal, lightPos - normal, bounds, out _))
!MathUtils.GetLineWorldRectangleIntersection(lightPos + normal, lightPos - normal, bounds, out _))
{
continue;
}
@@ -572,6 +573,7 @@ namespace Barotrauma.Lights
chList.List.Add(convexHull);
}
chList.IsHidden.RemoveWhere(ch => !chList.List.Contains(ch));
chList.HasBeenVisible.RemoveWhere(ch => !chList.List.Contains(ch));
HullsUpToDate.Add(sub);
}
@@ -592,7 +594,17 @@ namespace Barotrauma.Lights
private void CheckHullsInRange(Submarine sub)
{
//find the list of convexhulls that belong to the sub
ConvexHullList chList = convexHullsInRange.FirstOrDefault(chList => chList.Submarine == sub);
// Performance-sensitive code, hence implemented without Linq.
ConvexHullList chList = null;
foreach (var chl in convexHullsInRange)
{
if (chl.Submarine == sub)
{
chList = chl;
break;
}
}
//not found -> create one
if (chList == null)
@@ -604,7 +616,8 @@ namespace Barotrauma.Lights
foreach (var ch in chList.List)
{
if (ch.LastVertexChangeTime > LastRecalculationTime && !chList.IsHidden.Contains(ch))
if (ch.LastVertexChangeTime > LastRecalculationTime &&
(!chList.IsHidden.Contains(ch) || chList.HasBeenVisible.Contains(ch)))
{
NeedsRecalculation = true;
break;
@@ -712,8 +725,8 @@ namespace Barotrauma.Lights
{
foreach (ConvexHull hull in chList.List)
{
if (hull.IsInvalid) { continue; }
if (!chList.IsHidden.Contains(hull))
if (hull.IsInvalid || !hull.Enabled) { continue; }
if (!chList.IsHidden.Contains(hull) || chList.HasBeenVisible.Contains(hull))
{
//find convexhull segments that are close enough and facing towards the light source
lock (mutex)
@@ -732,7 +745,17 @@ namespace Barotrauma.Lights
}
foreach (ConvexHull hull in chList.List)
{
chList.IsHidden.Add(hull);
if (!hull.Enabled)
{
//if the hull is not enabled, we cannot determine if it's visible or hidden from the point of view of the light source
//so let's not mark it as hidden, but instead consider it as something that has been visible, so we know to recalculate if/when it becomes enabled again
chList.IsHidden.Remove(hull);
chList.HasBeenVisible.Add(hull);
continue;
}
//mark convex hulls as hidden at this point, they're removed if we find any of the segments to be visible
chList.IsHidden.Add(hull);
}
}
@@ -1411,14 +1434,7 @@ namespace Barotrauma.Lights
{
if (conditionals.None()) { return; }
if (conditionalTarget == null) { return; }
if (logicalOperator == PropertyConditional.LogicalOperatorType.And)
{
Enabled = conditionals.All(c => c.Matches(conditionalTarget));
}
else
{
Enabled = conditionals.Any(c => c.Matches(conditionalTarget));
}
Enabled = PropertyConditional.CheckConditionals(conditionalTarget, conditionals, logicalOperator);
}
public void DebugDrawVertices(SpriteBatch spriteBatch)
@@ -1501,6 +1517,7 @@ namespace Barotrauma.Lights
foreach (var convexHullList in convexHullsInRange)
{
convexHullList.IsHidden.Remove(visibleConvexHull);
convexHullList.HasBeenVisible.Add(visibleConvexHull);
}
}