Unstable 0.17.0.0

This commit is contained in:
Markus Isberg
2022-02-26 02:43:01 +09:00
parent a83f375681
commit 3974067915
913 changed files with 32472 additions and 32364 deletions
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Xml.Linq;
namespace Barotrauma
@@ -18,7 +19,7 @@ namespace Barotrauma
}
public string Name => $"Decorative Sprite";
public Dictionary<string, SerializableProperty> SerializableProperties { get; set; }
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; set; }
public Sprite Sprite { get; private set; }
@@ -29,22 +30,22 @@ namespace Barotrauma
Noise
}
[Serialize("0,0", true), Editable]
[Serialize("0,0", IsPropertySaveable.Yes), Editable]
public Vector2 Offset { get; private set; }
[Serialize("0,0", true), Editable]
[Serialize("0,0", IsPropertySaveable.Yes), Editable]
public Vector2 RandomOffset { get; private set; }
[Serialize(AnimationType.None, false), Editable]
[Serialize(AnimationType.None, IsPropertySaveable.No), Editable]
public AnimationType OffsetAnim { get; private set; }
[Serialize(0.0f, true), Editable]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable]
public float OffsetAnimSpeed { get; private set; }
private float rotationSpeedRadians;
private float absRotationSpeedRadians;
[Serialize(0.0f, true), Editable]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable]
public float RotationSpeed
{
get
@@ -59,7 +60,7 @@ namespace Barotrauma
}
private float rotationRadians;
[Serialize(0.0f, true), Editable]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable]
public float Rotation
{
get
@@ -73,7 +74,7 @@ namespace Barotrauma
}
private Vector2 randomRotationRadians;
[Serialize("0,0", true), Editable]
[Serialize("0,0", IsPropertySaveable.Yes), Editable]
public Vector2 RandomRotation
{
get
@@ -87,30 +88,30 @@ namespace Barotrauma
}
private float scale;
[Serialize(1.0f, true), Editable]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable]
public float Scale
{
get { return scale; }
private set { scale = MathHelper.Clamp(value, 0.0f, 10.0f); }
}
[Serialize("0,0", true), Editable]
[Serialize("0,0", IsPropertySaveable.Yes), Editable]
public Vector2 RandomScale
{
get;
private set;
}
[Serialize(AnimationType.None, false), Editable]
[Serialize(AnimationType.None, IsPropertySaveable.No), Editable]
public AnimationType RotationAnim { get; private set; }
/// <summary>
/// If > 0, only one sprite of the same group is used (chosen randomly)
/// </summary>
[Serialize(0, false, description: "If > 0, only one sprite of the same group is used (chosen randomly)"), Editable(ReadOnly = true)]
[Serialize(0, IsPropertySaveable.No, description: "If > 0, only one sprite of the same group is used (chosen randomly)"), Editable(ReadOnly = true)]
public int RandomGroupID { get; private set; }
[Serialize("1.0,1.0,1.0,1.0", true), Editable()]
[Serialize("1.0,1.0,1.0,1.0", IsPropertySaveable.Yes), Editable()]
public Color Color { get; set; }
/// <summary>
@@ -122,12 +123,12 @@ namespace Barotrauma
/// </summary>
internal List<PropertyConditional> AnimationConditionals { get; private set; } = new List<PropertyConditional>();
public DecorativeSprite(XElement element, string path = "", string file = "", bool lazyLoad = false)
public DecorativeSprite(ContentXElement element, string path = "", string file = "", bool lazyLoad = false)
{
Sprite = new Sprite(element, path, file, lazyLoad: lazyLoad);
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
// load property conditionals
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
//choose which list the new conditional should be placed to
List<PropertyConditional> conditionalList = null;
@@ -217,18 +218,18 @@ namespace Barotrauma
return MathHelper.Lerp(RandomScale.X, RandomScale.Y, randomScaleModifier);
}
public static void UpdateSpriteStates(Dictionary<int, List<DecorativeSprite>> spriteGroups, Dictionary<DecorativeSprite, State> animStates,
public static void UpdateSpriteStates(ImmutableDictionary<int, ImmutableArray<DecorativeSprite>> spriteGroups, Dictionary<DecorativeSprite, State> animStates,
int entityID, float deltaTime, Func<PropertyConditional, bool> checkConditional)
{
foreach (int spriteGroup in spriteGroups.Keys)
{
for (int i = 0; i < spriteGroups[spriteGroup].Count; i++)
for (int i = 0; i < spriteGroups[spriteGroup].Length; i++)
{
var decorativeSprite = spriteGroups[spriteGroup][i];
if (decorativeSprite == null) { continue; }
if (spriteGroup > 0)
{
int activeSpriteIndex = entityID % spriteGroups[spriteGroup].Count;
int activeSpriteIndex = entityID % spriteGroups[spriteGroup].Length;
if (i != activeSpriteIndex)
{
animStates[decorativeSprite].IsActive = false;
@@ -9,11 +9,11 @@ namespace Barotrauma.SpriteDeformations
class CustomDeformationParams : SpriteDeformationParams
{
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f),
Serialize(0.0f, true, description: "How fast the deformation \"oscillates\" back and forth. " +
Serialize(0.0f, IsPropertySaveable.Yes, description: "How fast the deformation \"oscillates\" back and forth. " +
"For example, if the sprite is stretched up, setting this value above zero would make it do a wave-like movement up and down.")]
public override float Frequency { get; set; } = 1;
[Serialize(1.0f, true, description: "The \"strength\" of the deformation."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
[Serialize(1.0f, IsPropertySaveable.Yes, description: "The \"strength\" of the deformation."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
public float Amplitude { get; set; }
public CustomDeformationParams(XElement element) : base(element)
@@ -6,9 +6,9 @@ namespace Barotrauma.SpriteDeformations
{
class InflateParams : SpriteDeformationParams
{
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ValueStep = 1)]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ValueStep = 1)]
public override float Frequency { get; set; } = 1;
[Serialize(1.0f, true), Editable(MinValueFloat = 0.01f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.1f)]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.01f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.1f)]
public float Scale { get; set; }
public InflateParams(XElement element) : base(element)
@@ -5,13 +5,13 @@ namespace Barotrauma.SpriteDeformations
{
class NoiseDeformationParams : SpriteDeformationParams
{
[Serialize(0.0f, true, description: "The frequency of the noise."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ValueStep = 1f)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "The frequency of the noise."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ValueStep = 1f)]
public override float Frequency { get; set; }
[Serialize(1.0f, true, description: "How much the noise distorts the sprite."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.01f)]
[Serialize(1.0f, IsPropertySaveable.Yes, description: "How much the noise distorts the sprite."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.01f)]
public float Amplitude { get; set; }
[Serialize(0.0f, true, description: "How fast the noise changes."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.01f)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "How fast the noise changes."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f, DecimalCount = 2, ValueStep = 0.01f)]
public float ChangeSpeed { get; set; }
public NoiseDeformationParams(XElement element) : base(element)
@@ -10,26 +10,26 @@ namespace Barotrauma.SpriteDeformations
/// 0 = no falloff, the entire sprite is stretched
/// 1 = stretching the center of the sprite has no effect at the edges
/// </summary>
[Serialize(0.0f, true, description: "0 = no falloff, the entire sprite is stretched, 1 = stretching the center of the sprite has no effect at the edges."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "0 = no falloff, the entire sprite is stretched, 1 = stretching the center of the sprite has no effect at the edges."), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f)]
public float Falloff { get; set; }
/// <summary>
/// Maximum stretch per vertex (1 = the size of the sprite)
/// </summary>
[Serialize(1.0f, true, description: "Maximum stretch per vertex (1 = the size of the sprite)"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
[Serialize(1.0f, IsPropertySaveable.Yes, description: "Maximum stretch per vertex (1 = the size of the sprite)"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
public float MaxDeformation { get; set; }
/// <summary>
/// How fast the sprite reacts to being stretched
/// </summary>
[Serialize(10.0f, true, description: "How fast the sprite reacts to being stretched"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
[Serialize(10.0f, IsPropertySaveable.Yes, description: "How fast the sprite reacts to being stretched"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
public float ReactionSpeed { get; set; }
/// <summary>
/// How fast the sprite returns back to normal after stretching ends
/// </summary>
[Serialize(0.05f, true, description: "How fast the sprite returns back to normal after stretching ends"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
[Serialize(0.05f, IsPropertySaveable.Yes, description: "How fast the sprite returns back to normal after stretching ends"), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
public float RecoverSpeed { get; set; }
public PositionalDeformationParams(XElement element) : base(element)
@@ -14,21 +14,21 @@ namespace Barotrauma.SpriteDeformations
/// A positive value means that this deformation is or could be used for multiple sprites.
/// This behaviour is not automatic, and has to be implemented for any particular case separately (currently only used in Limbs).
/// </summary>
[Serialize(-1, true), Editable(minValue: -1, maxValue: 100)]
[Serialize(-1, IsPropertySaveable.Yes), Editable(minValue: -1, maxValue: 100)]
public int Sync
{
get;
private set;
}
[Serialize("", true)]
[Serialize("", IsPropertySaveable.Yes)]
public string TypeName
{
get;
set;
}
[Serialize(SpriteDeformation.DeformationBlendMode.Add, true), Editable]
[Serialize(SpriteDeformation.DeformationBlendMode.Add, IsPropertySaveable.Yes), Editable]
public SpriteDeformation.DeformationBlendMode BlendMode
{
get;
@@ -37,30 +37,30 @@ namespace Barotrauma.SpriteDeformations
public string Name => $"Deformation ({TypeName})";
[Serialize(1.0f, true), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
public float Strength { get; private set; }
[Serialize(90f, true), Editable(MinValueFloat = 0, MaxValueFloat = 90)]
[Serialize(90f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 90)]
public float MaxRotation { get; private set; }
[Serialize(false, true), Editable]
[Serialize(false, IsPropertySaveable.Yes), Editable]
public bool UseMovementSine { get; set; }
[Serialize(false, true), Editable]
[Serialize(false, IsPropertySaveable.Yes), Editable]
public bool StopWhenHostIsDead { get; set; }
[Serialize(false, true), Editable]
[Serialize(false, IsPropertySaveable.Yes), Editable]
public bool OnlyInWater { get; set; }
/// <summary>
/// Only used if UseMovementSine is enabled. Multiplier for Pi.
/// </summary>
[Serialize(0f, true), Editable]
[Serialize(0f, IsPropertySaveable.Yes), Editable]
public float SineOffset { get; set; }
public virtual float Frequency { get; set; } = 1;
public Dictionary<string, SerializableProperty> SerializableProperties
public Dictionary<Identifier, SerializableProperty> SerializableProperties
{
get;
set;
@@ -72,7 +72,7 @@ namespace Barotrauma.SpriteDeformations
public static readonly Point ShaderMaxResolution = new Point(15, 15);
private Point _resolution;
[Serialize("2,2", true)]
[Serialize("2,2", IsPropertySaveable.Yes)]
public Point Resolution
{
get { return _resolution; }
@@ -345,7 +345,7 @@ namespace Barotrauma
};
new GUITextBlock(new RectTransform(new Point(container.Rect.Width, (int)(60 * GUI.Scale)), container.RectTransform) { IsFixedSize = true },
"Sprite Deformations", textAlignment: Alignment.BottomCenter, font: GUI.LargeFont);
"Sprite Deformations", textAlignment: Alignment.BottomCenter, font: GUIStyle.LargeFont);
var resolutionField = GUI.CreatePointField(new Point(subDivX + 1, subDivY + 1), (int)(30 * GUI.Scale), "Resolution", container.RectTransform,
"How many vertices the deformable sprite has on the x and y axes. Larger values make the deformations look smoother, but are more performance intensive.");
@@ -387,7 +387,7 @@ namespace Barotrauma
foreach (SpriteDeformation deformation in deformations)
{
var deformEditor = new SerializableEntityEditor(container.RectTransform, deformation.Params,
inGame: false, showName: true, titleFont: GUI.SubHeadingFont);
inGame: false, showName: true, titleFont: GUIStyle.SubHeadingFont);
deformEditor.RectTransform.MinSize = new Point(deformEditor.Rect.Width, deformEditor.Rect.Height);
}
@@ -10,11 +10,19 @@ namespace Barotrauma
{
public partial class Sprite
{
private class TextureRefCounter
{
public Texture2D Texture;
public int RefCount;
}
private readonly static Dictionary<Identifier, TextureRefCounter> textureRefCounts = new Dictionary<Identifier, TextureRefCounter>();
private bool cannotBeLoaded;
protected volatile bool loadingAsync = false;
protected Texture2D texture;
protected Texture2D texture { get; private set; }
public Texture2D Texture
{
get
@@ -24,6 +32,8 @@ namespace Barotrauma
}
}
private string disposeStackTrace;
public bool Loaded
{
get { return texture != null && !cannotBeLoaded; }
@@ -32,7 +42,6 @@ namespace Barotrauma
public Sprite(Sprite other) : this(other.texture, other.sourceRect, other.offset, other.rotation)
{
FilePath = other.FilePath;
FullPath = other.FullPath;
Compress = other.Compress;
size = other.size;
effects = other.effects;
@@ -47,18 +56,13 @@ namespace Barotrauma
origin = Vector2.Zero;
effects = SpriteEffects.None;
rotation = newRotation;
FilePath = path;
FilePath = ContentPath.FromRaw(path);
AddToList(this);
}
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn)
{
texture = LoadTexture(this.FilePath, out Sprite reusedSprite, Compress);
if (reusedSprite != null)
{
FilePath = string.Intern(reusedSprite.FilePath);
FullPath = string.Intern(reusedSprite.FullPath);
}
texture = LoadTexture(FilePath.Value, Compress);
if (texture == null)
{
@@ -118,7 +122,7 @@ namespace Barotrauma
public void ReloadTexture(IEnumerable<Sprite> spritesToUpdate)
{
texture.Dispose();
texture = TextureLoader.FromFile(FilePath, Compress);
texture = TextureLoader.FromFile(FilePath.Value, Compress);
foreach (Sprite sprite in spritesToUpdate)
{
sprite.texture = texture;
@@ -130,14 +134,8 @@ namespace Barotrauma
sourceRect = new Rectangle(0, 0, texture.Width, texture.Height);
}
public static Texture2D LoadTexture(string file)
public static Texture2D LoadTexture(string file, bool compress = true)
{
return LoadTexture(file, out _);
}
public static Texture2D LoadTexture(string file, out Sprite reusedSprite, bool compress = true)
{
reusedSprite = null;
if (string.IsNullOrWhiteSpace(file))
{
Texture2D t = null;
@@ -147,9 +145,15 @@ namespace Barotrauma
});
return t;
}
string fullPath = Path.GetFullPath(file);
reusedSprite = FindMatchingSprite(fullPath, requireTexture: true);
if (reusedSprite != null) { return reusedSprite.texture; }
Identifier fullPath = Path.GetFullPath(file).CleanUpPathCrossPlatform(correctFilenameCase: false).ToIdentifier();
lock (list)
{
if (textureRefCounts.ContainsKey(fullPath))
{
textureRefCounts[fullPath].RefCount++;
return textureRefCounts[fullPath].Texture;
}
}
if (File.Exists(file))
{
@@ -159,7 +163,13 @@ namespace Barotrauma
DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!");
#endif
}
return TextureLoader.FromFile(file, compress);
Texture2D newTexture = TextureLoader.FromFile(file, compress);
lock (list)
{
textureRefCounts.Add(fullPath, new TextureRefCounter { RefCount = 1, Texture = newTexture });
}
return newTexture;
}
else
{
@@ -170,22 +180,6 @@ namespace Barotrauma
return null;
}
private static Sprite FindMatchingSprite(string fullPath, bool requireTexture)
{
lock (list)
{
foreach (var wRef in list)
{
if (wRef.TryGetTarget(out Sprite sprite))
{
bool hasTexture = sprite.texture != null && !sprite.texture.IsDisposed;
if (sprite.FullPath == fullPath && (hasTexture || !requireTexture)) { return sprite; }
}
}
}
return null;
}
public void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate = 0.0f, float scale = 1.0f, SpriteEffects spriteEffect = SpriteEffects.None)
{
this.Draw(spriteBatch, pos, Color.White, rotate, scale, spriteEffect);
@@ -378,15 +372,33 @@ namespace Barotrauma
partial void DisposeTexture()
{
//check if another sprite is using the same texture
if (!string.IsNullOrEmpty(FilePath)) //file can be empty if the sprite is created directly from a Texture2D instance
{
if (FindMatchingSprite(FullPath, requireTexture: false) != null) { return; }
}
//if not, free the texture
disposeStackTrace = Environment.StackTrace;
if (texture != null)
{
//check if another sprite is using the same texture
lock (list)
{
if (!FilePath.IsNullOrEmpty()) //file can be empty if the sprite is created directly from a Texture2D instance
{
Identifier pathKey = FullPath.ToIdentifier();
if (!pathKey.IsEmpty && textureRefCounts.ContainsKey(pathKey))
{
textureRefCounts[pathKey].RefCount--;
if (textureRefCounts[pathKey].RefCount <= 0)
{
textureRefCounts.Remove(pathKey);
}
else
{
texture = null;
FilePath = ContentPath.Empty;
return;
}
}
}
}
//if not, free the texture
CrossThread.RequestExecutionOnMainThread(() =>
{
texture.Dispose();