(61d00a474) v0.9.7.1
This commit is contained in:
+139
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
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. " +
|
||||
"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)]
|
||||
public float Amplitude { get; set; }
|
||||
|
||||
public CustomDeformationParams(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDeformation : SpriteDeformation
|
||||
{
|
||||
private List<Vector2[]> deformRows = new List<Vector2[]>();
|
||||
|
||||
private CustomDeformationParams CustomDeformationParams => Params as CustomDeformationParams;
|
||||
|
||||
public override float Phase
|
||||
{
|
||||
get { return phase; }
|
||||
set
|
||||
{
|
||||
phase = value;
|
||||
//phase %= MathHelper.TwoPi;
|
||||
}
|
||||
}
|
||||
private float phase;
|
||||
|
||||
public CustomDeformation(XElement element) : base(element, new CustomDeformationParams(element))
|
||||
{
|
||||
phase = Rand.Range(0.0f, MathHelper.TwoPi);
|
||||
|
||||
if (element == null)
|
||||
{
|
||||
deformRows.Add(new Vector2[] { Vector2.Zero, Vector2.Zero });
|
||||
deformRows.Add(new Vector2[] { Vector2.Zero, Vector2.Zero });
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
string row = element.GetAttributeString("row" + i, "");
|
||||
if (string.IsNullOrWhiteSpace(row)) break;
|
||||
|
||||
string[] splitRow = row.Split(' ');
|
||||
Vector2[] rowVectors = new Vector2[splitRow.Length];
|
||||
for (int j = 0; j < splitRow.Length; j++)
|
||||
{
|
||||
rowVectors[j] = XMLExtensions.ParseVector2(splitRow[j]);
|
||||
}
|
||||
deformRows.Add(rowVectors);
|
||||
}
|
||||
}
|
||||
|
||||
if (deformRows.Count() == 0 || deformRows.First() == null || deformRows.First().Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var configDeformation = new Vector2[deformRows.First().Length, deformRows.Count];
|
||||
for (int x = 0; x < configDeformation.GetLength(0); x++)
|
||||
{
|
||||
for (int y = 0; y < configDeformation.GetLength(1); y++)
|
||||
{
|
||||
configDeformation[x, y] = deformRows[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
//construct an array for the desired resolution,
|
||||
//interpolating values if the resolution configured in the xml is smaller
|
||||
//deformation = new Vector2[Resolution.X, Resolution.Y];
|
||||
float divX = 1.0f / Resolution.X, divY = 1.0f / Resolution.Y;
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
float normalizedX = x / (float)(Resolution.X - 1);
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
float normalizedY = y / (float)(Resolution.Y - 1);
|
||||
|
||||
Point indexTopLeft = new Point(
|
||||
Math.Min((int)Math.Floor(normalizedX * (configDeformation.GetLength(0) - 1)), configDeformation.GetLength(0) - 1),
|
||||
Math.Min((int)Math.Floor(normalizedY * (configDeformation.GetLength(1) - 1)), configDeformation.GetLength(1) - 1));
|
||||
Point indexBottomRight = new Point(
|
||||
Math.Min(indexTopLeft.X + 1, configDeformation.GetLength(0) - 1),
|
||||
Math.Min(indexTopLeft.Y + 1, configDeformation.GetLength(1) - 1));
|
||||
|
||||
Vector2 deformTopLeft = configDeformation[indexTopLeft.X, indexTopLeft.Y];
|
||||
Vector2 deformTopRight = configDeformation[indexBottomRight.X, indexTopLeft.Y];
|
||||
Vector2 deformBottomLeft = configDeformation[indexTopLeft.X, indexBottomRight.Y];
|
||||
Vector2 deformBottomRight = configDeformation[indexBottomRight.X, indexBottomRight.Y];
|
||||
|
||||
Deformation[x, y] = Vector2.Lerp(
|
||||
Vector2.Lerp(deformTopLeft, deformTopRight, (normalizedX % divX) / divX),
|
||||
Vector2.Lerp(deformBottomLeft, deformBottomRight, (normalizedX % divX) / divX),
|
||||
(normalizedY % divY) / divY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetDeformation(out Vector2[,] deformation, out float multiplier)
|
||||
{
|
||||
deformation = Deformation;
|
||||
multiplier = CustomDeformationParams.Frequency <= 0.0f ?
|
||||
CustomDeformationParams.Amplitude :
|
||||
(float)Math.Sin(phase) * CustomDeformationParams.Amplitude;
|
||||
multiplier *= Params.Strength;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (!Params.UseMovementSine)
|
||||
{
|
||||
phase += deltaTime * CustomDeformationParams.Frequency;
|
||||
phase %= MathHelper.TwoPi;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
base.Save(element);
|
||||
for (int i = 0; i < deformRows.Count; i++)
|
||||
{
|
||||
element.Add(new XAttribute("row" + i, string.Join(" ", deformRows[i].Select(r => XMLExtensions.Vector2ToString(r)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.SpriteDeformations
|
||||
{
|
||||
class InflateParams : SpriteDeformationParams
|
||||
{
|
||||
[Serialize(0.0f, true), 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)]
|
||||
public float Scale { get; set; }
|
||||
|
||||
public InflateParams(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class Inflate : SpriteDeformation
|
||||
{
|
||||
public override float Phase
|
||||
{
|
||||
get { return phase; }
|
||||
set
|
||||
{
|
||||
phase = value;
|
||||
//phase %= MathHelper.TwoPi;
|
||||
}
|
||||
}
|
||||
private float phase;
|
||||
|
||||
private Vector2[,] deformation;
|
||||
|
||||
private InflateParams InflateParams => Params as InflateParams;
|
||||
|
||||
public Inflate(XElement element) : base(element, new InflateParams(element))
|
||||
{
|
||||
deformation = new Vector2[Resolution.X, Resolution.Y];
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
float normalizedX = x / (float)(Resolution.X - 1);
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
float normalizedY = y / (float)(Resolution.X - 1);
|
||||
|
||||
Vector2 centerDiff = new Vector2(normalizedX - 0.5f, normalizedY - 0.5f);
|
||||
float centerDist = centerDiff.Length() * 2.0f;
|
||||
if (centerDist == 0.0f) continue;
|
||||
|
||||
deformation[x, y] = (centerDiff / centerDist) * Math.Min(1.0f, centerDist);
|
||||
}
|
||||
}
|
||||
|
||||
phase = Rand.Range(0.0f, MathHelper.TwoPi);
|
||||
}
|
||||
|
||||
protected override void GetDeformation(out Vector2[,] deformation, out float multiplier)
|
||||
{
|
||||
deformation = this.deformation;
|
||||
multiplier = InflateParams.Frequency <= 0.0f ? InflateParams.Scale : (float)(Math.Sin(phase) + 1.0f) / 2.0f * InflateParams.Scale;
|
||||
multiplier *= Params.Strength;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (!Params.UseMovementSine)
|
||||
{
|
||||
phase += deltaTime * InflateParams.Frequency;
|
||||
phase %= MathHelper.TwoPi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.SpriteDeformations
|
||||
{
|
||||
class JointBendDeformationParams : SpriteDeformationParams
|
||||
{
|
||||
public JointBendDeformationParams(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does a rotational deformations around pivot points at the edges of the sprite.
|
||||
/// </summary>
|
||||
class JointBendDeformation : SpriteDeformation
|
||||
{
|
||||
//how much to bend at the right side of the sprite
|
||||
private float bendRight;
|
||||
public float BendRight
|
||||
{
|
||||
get { return bendRight; }
|
||||
set { bendRight = MathHelper.Clamp(value, -MaxRotationInRadians, MaxRotationInRadians); }
|
||||
}
|
||||
//the pivot point to rotate the right side around
|
||||
public Vector2 BendRightRefPos = new Vector2(1.0f, 0.5f);
|
||||
|
||||
private float bendLeft;
|
||||
public float BendLeft
|
||||
{
|
||||
get { return bendLeft; }
|
||||
set { bendLeft = MathHelper.Clamp(value, -MaxRotationInRadians, MaxRotationInRadians); }
|
||||
}
|
||||
public Vector2 BendLeftRefPos = new Vector2(0.0f, 0.5f);
|
||||
|
||||
private float bendUp;
|
||||
public float BendUp
|
||||
{
|
||||
get { return bendUp; }
|
||||
set { bendUp = MathHelper.Clamp(value, -MaxRotationInRadians, MaxRotationInRadians); }
|
||||
}
|
||||
public Vector2 BendUpRefPos = new Vector2(0.5f, 0.0f);
|
||||
|
||||
private float bendDown;
|
||||
public float BendDown
|
||||
{
|
||||
get { return bendDown; }
|
||||
set { bendDown = MathHelper.Clamp(value, -MaxRotationInRadians, MaxRotationInRadians); }
|
||||
}
|
||||
public Vector2 BendDownRefPos = new Vector2(0.5f, 1.0f);
|
||||
|
||||
public Vector2 Scale = Vector2.Zero;
|
||||
|
||||
private float MaxRotationInRadians => MathHelper.ToRadians(Params.MaxRotation);
|
||||
|
||||
public JointBendDeformation(XElement element) : base(element, new JointBendDeformationParams(element)) { }
|
||||
|
||||
protected override void GetDeformation(out Vector2[,] deformation, out float multiplier)
|
||||
{
|
||||
deformation = Deformation;
|
||||
multiplier = 1.0f;// this.multiplier;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
Vector2 normalizedPos = Vector2.Zero;
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
normalizedPos.X = x / (float)(Resolution.X - 1);
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
normalizedPos.Y = y / (float)(Resolution.Y - 1);
|
||||
Deformation[x, y] = Vector2.Zero;
|
||||
|
||||
if (Math.Abs(BendLeft) > 0.001f)
|
||||
{
|
||||
float strength = 1.0f - normalizedPos.X;//(1.0f - Math.Max(normalizedPos.X - BendLeftRefPos.X, 0.0f) / (1.0f - BendLeftRefPos.X));
|
||||
strength = (strength - 0.5f) * 2.0f;
|
||||
if (strength > 0.0f)
|
||||
{
|
||||
Vector2 rotatedP = RotatePointAroundTarget(normalizedPos, BendLeftRefPos, BendLeft * strength * Params.Strength);
|
||||
Vector2 offset = rotatedP - normalizedPos;
|
||||
offset.X *= Scale.Y / Scale.X;
|
||||
Deformation[x, y] += offset;
|
||||
}
|
||||
}
|
||||
if (Math.Abs(BendRight) > 0.001f)
|
||||
{
|
||||
float strength = normalizedPos.X;//(1.0f - Math.Max(BendRightRefPos.X - normalizedPos.X, 0.0f) / (BendRightRefPos.X));
|
||||
strength = (strength - 0.5f) * 2.0f;
|
||||
if (strength > 0.0f)
|
||||
{
|
||||
Vector2 rotatedP = RotatePointAroundTarget(normalizedPos, BendRightRefPos, BendRight * strength * Params.Strength);
|
||||
Vector2 offset = rotatedP - normalizedPos;
|
||||
offset.X *= Scale.Y / Scale.X;
|
||||
Deformation[x, y] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.Abs(BendUp) > 0.001f)
|
||||
{
|
||||
float strength = 1.0f - normalizedPos.Y;//(1.0f - Math.Max(normalizedPos.Y - BendUpRefPos.Y, 0.0f) / (1.0f - BendUpRefPos.Y));
|
||||
strength = (strength - 0.5f) * 2.0f;
|
||||
if (strength > 0.0f)
|
||||
{
|
||||
Vector2 rotatedP = RotatePointAroundTarget(normalizedPos, BendUpRefPos, BendUp * strength * Params.Strength);
|
||||
Vector2 offset = rotatedP - normalizedPos;
|
||||
offset.Y *= Scale.X / Scale.Y;
|
||||
Deformation[x, y] += offset;
|
||||
}
|
||||
}
|
||||
if (Math.Abs(BendDown) > 0.001f)
|
||||
{
|
||||
float strength = normalizedPos.Y;//(1.0f - Math.Max(BendDownRefPos.Y - normalizedPos.Y, 0.0f) / (BendDownRefPos.Y));
|
||||
strength = (strength - 0.5f) * 2.0f;
|
||||
if (strength > 0.0f)
|
||||
{
|
||||
Vector2 rotatedP = RotatePointAroundTarget(normalizedPos, BendDownRefPos, BendDown * strength * Params.Strength);
|
||||
Vector2 offset = rotatedP - normalizedPos;
|
||||
offset.Y *= Scale.X / Scale.Y;
|
||||
Deformation[x, y] += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector2 RotatePointAroundTarget(Vector2 point, Vector2 target, float angle)
|
||||
{
|
||||
return RotatePointAroundTarget(point, target, (float)Math.Sin(angle), (float)Math.Cos(angle));
|
||||
}
|
||||
|
||||
public static Vector2 RotatePointAroundTarget(Vector2 point, Vector2 target, float sin, float cos)
|
||||
{
|
||||
Vector2 dir = point - target;
|
||||
var x = (cos * dir.X) - (sin * dir.Y) + target.X;
|
||||
var y = (sin * dir.X) + (cos * dir.Y) + target.Y;
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Xml.Linq;
|
||||
|
||||
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)]
|
||||
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)]
|
||||
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)]
|
||||
public float ChangeSpeed { get; set; }
|
||||
|
||||
public NoiseDeformationParams(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class NoiseDeformation : SpriteDeformation
|
||||
{
|
||||
private NoiseDeformationParams NoiseDeformationParams => Params as NoiseDeformationParams;
|
||||
|
||||
private float phase;
|
||||
|
||||
public NoiseDeformation(XElement element) : base(element, new NoiseDeformationParams(element))
|
||||
{
|
||||
phase = Rand.Range(0.0f, 255.0f);
|
||||
UpdateNoise();
|
||||
}
|
||||
|
||||
private void UpdateNoise()
|
||||
{
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
float normalizedX = x / (float)(Resolution.X - 1) * NoiseDeformationParams.Frequency;
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
float normalizedY = y / (float)(Resolution.X - 1) * NoiseDeformationParams.Frequency;
|
||||
|
||||
Deformation[x, y] = new Vector2(
|
||||
PerlinNoise.GetPerlin(normalizedX + phase, normalizedY + phase) - 0.5f,
|
||||
PerlinNoise.GetPerlin(normalizedY - phase, normalizedX - phase) - 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetDeformation(out Vector2[,] deformation, out float multiplier)
|
||||
{
|
||||
deformation = Deformation;
|
||||
multiplier = NoiseDeformationParams.Amplitude * Params.Strength;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (NoiseDeformationParams.ChangeSpeed > 0.0f)
|
||||
{
|
||||
phase += deltaTime * NoiseDeformationParams.ChangeSpeed / 100.0f;
|
||||
phase %= 1.0f;
|
||||
UpdateNoise();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.SpriteDeformations
|
||||
{
|
||||
class PositionalDeformationParams : SpriteDeformationParams
|
||||
{
|
||||
/// <summary>
|
||||
/// 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)]
|
||||
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)]
|
||||
public float MaxDeformation { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How fast the sprite reacts to being stretched
|
||||
/// </summary>
|
||||
[Serialize(1.0f, true, 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.1f, true, 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Stretch a position in the deformable sprite to some direction
|
||||
/// </summary>
|
||||
class PositionalDeformation : SpriteDeformation
|
||||
{
|
||||
public enum ReactionType
|
||||
{
|
||||
ReactToTriggerers
|
||||
}
|
||||
|
||||
public ReactionType Type;
|
||||
|
||||
private PositionalDeformationParams positionalDeformationParams => Params as PositionalDeformationParams;
|
||||
|
||||
public PositionalDeformation(XElement element) : base(element, new PositionalDeformationParams(element))
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (positionalDeformationParams.RecoverSpeed <= 0.0f) return;
|
||||
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
if (Deformation[x,y].LengthSquared() < 0.0001f)
|
||||
{
|
||||
Deformation[x, y] = Vector2.Zero;
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 reduction = Deformation[x, y];
|
||||
Deformation[x, y] -= reduction.ClampLength(positionalDeformationParams.RecoverSpeed) * deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deform(Vector2 worldPosition, Vector2 amount, float deltaTime, Matrix transformMatrix)
|
||||
{
|
||||
Vector2 pos = Vector2.Transform(worldPosition, transformMatrix);
|
||||
Point deformIndex = new Point((int)(pos.X * (Resolution.X - 1)), (int)(pos.Y * (Resolution.Y - 1)));
|
||||
|
||||
if (deformIndex.X < 0 || deformIndex.Y < 0) return;
|
||||
if (deformIndex.X >= Resolution.X || deformIndex.Y >= Resolution.Y) return;
|
||||
|
||||
amount = amount.ClampLength(positionalDeformationParams.MaxDeformation);
|
||||
|
||||
float invFalloff = 1.0f - positionalDeformationParams.Falloff;
|
||||
|
||||
for (int x = 0; x < Resolution.X; x++)
|
||||
{
|
||||
float normalizedDiffX = Math.Abs(x - deformIndex.X) / (Resolution.X * 0.5f);
|
||||
for (int y = 0; y < Resolution.Y; y++)
|
||||
{
|
||||
float normalizedDiffY = Math.Abs(y - deformIndex.Y) / (Resolution.Y * 0.5f);
|
||||
Vector2 targetDeformation = amount * MathHelper.Clamp(1.0f - new Vector2(normalizedDiffX, normalizedDiffY).Length() * positionalDeformationParams.Falloff, 0.0f, 1.0f);
|
||||
|
||||
Vector2 diff = targetDeformation - Deformation[x, y];
|
||||
Deformation[x, y] += diff.ClampLength(positionalDeformationParams.ReactionSpeed) * deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetDeformation(out Vector2[,] deformation, out float multiplier)
|
||||
{
|
||||
deformation = Deformation;
|
||||
multiplier = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.SpriteDeformations
|
||||
{
|
||||
abstract class SpriteDeformationParams : ISerializableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// A negative value means that the deformation is used only by one sprite only (default).
|
||||
/// 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)]
|
||||
public int Sync
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize("", true)]
|
||||
public string TypeName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(SpriteDeformation.DeformationBlendMode.Add, true), Editable]
|
||||
public SpriteDeformation.DeformationBlendMode BlendMode
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Name => $"Deformation ({TypeName})";
|
||||
|
||||
[Serialize(1.0f, true), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
|
||||
public float Strength { get; private set; }
|
||||
|
||||
[Serialize(90f, true), Editable(MinValueFloat = 0, MaxValueFloat = 90)]
|
||||
public float MaxRotation { get; private set; }
|
||||
|
||||
[Serialize(false, true), Editable]
|
||||
public bool UseMovementSine { get; set; }
|
||||
|
||||
[Serialize(false, true), Editable]
|
||||
public bool StopWhenHostIsDead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only used if UseMovementSine is enabled. Multiplier for Pi.
|
||||
/// </summary>
|
||||
[Serialize(0f, true), Editable]
|
||||
public float SineOffset { get; set; }
|
||||
|
||||
public virtual float Frequency { get; set; } = 1;
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defined in the shader.
|
||||
/// </summary>
|
||||
public static readonly Point ShaderMaxResolution = new Point(15, 15);
|
||||
|
||||
private Point _resolution;
|
||||
[Serialize("2,2", true)]
|
||||
public Point Resolution
|
||||
{
|
||||
get { return _resolution; }
|
||||
set
|
||||
{
|
||||
if (_resolution == value) { return; }
|
||||
_resolution = value.Clamp(new Point(2, 2), ShaderMaxResolution);
|
||||
}
|
||||
}
|
||||
|
||||
public SpriteDeformationParams(XElement element)
|
||||
{
|
||||
if (element != null)
|
||||
{
|
||||
TypeName = element.GetAttributeString("type", "").ToLowerInvariant();
|
||||
}
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SpriteDeformation
|
||||
{
|
||||
public enum DeformationBlendMode
|
||||
{
|
||||
Add,
|
||||
Multiply,
|
||||
Override
|
||||
}
|
||||
|
||||
public virtual float Phase { get; set; }
|
||||
|
||||
protected Vector2[,] Deformation { get; private set; }
|
||||
|
||||
public SpriteDeformationParams Params { get; set; }
|
||||
|
||||
private static readonly string[] deformationTypes = new string[] { "Inflate", "Custom", "Noise", "BendJoint", "ReactToTriggerers" };
|
||||
public static IEnumerable<string> DeformationTypes
|
||||
{
|
||||
get { return deformationTypes; }
|
||||
}
|
||||
|
||||
public Point Resolution
|
||||
{
|
||||
get { return Params.Resolution; }
|
||||
set { SetResolution(value); }
|
||||
}
|
||||
|
||||
public string TypeName => Params.TypeName;
|
||||
|
||||
public int Sync => Params.Sync;
|
||||
|
||||
public static SpriteDeformation Load(string deformationType, string parentDebugName)
|
||||
{
|
||||
return Load(null, deformationType, parentDebugName);
|
||||
}
|
||||
public static SpriteDeformation Load(XElement element, string parentDebugName)
|
||||
{
|
||||
return Load(element, null, parentDebugName);
|
||||
}
|
||||
|
||||
private static SpriteDeformation Load(XElement element, string deformationType, string parentDebugName)
|
||||
{
|
||||
string typeName = deformationType;
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
typeName = element.GetAttributeString("typename", null) ?? element.GetAttributeString("type", "");
|
||||
}
|
||||
|
||||
SpriteDeformation newDeformation = null;
|
||||
switch (typeName.ToLowerInvariant())
|
||||
{
|
||||
case "inflate":
|
||||
newDeformation = new Inflate(element);
|
||||
break;
|
||||
case "custom":
|
||||
newDeformation = new CustomDeformation(element);
|
||||
break;
|
||||
case "noise":
|
||||
newDeformation = new NoiseDeformation(element);
|
||||
break;
|
||||
case "jointbend":
|
||||
case "bendjoint":
|
||||
newDeformation = new JointBendDeformation(element);
|
||||
break;
|
||||
case "reacttotriggerers":
|
||||
return new PositionalDeformation(element);
|
||||
default:
|
||||
if (Enum.TryParse(typeName, out PositionalDeformation.ReactionType reactionType))
|
||||
{
|
||||
newDeformation = new PositionalDeformation(element)
|
||||
{
|
||||
Type = reactionType
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Could not load sprite deformation animation in " + parentDebugName + " - \"" + typeName + "\" is not a valid deformation type.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (newDeformation != null)
|
||||
{
|
||||
newDeformation.Params.TypeName = typeName;
|
||||
}
|
||||
return newDeformation;
|
||||
}
|
||||
|
||||
protected SpriteDeformation(XElement element, SpriteDeformationParams deformationParams)
|
||||
{
|
||||
this.Params = deformationParams;
|
||||
SerializableProperty.DeserializeProperties(deformationParams, element);
|
||||
Deformation = new Vector2[deformationParams.Resolution.X, deformationParams.Resolution.Y];
|
||||
}
|
||||
|
||||
public void SetResolution(Point resolution)
|
||||
{
|
||||
Params.Resolution = resolution;
|
||||
Deformation = new Vector2[Params.Resolution.X, Params.Resolution.Y];
|
||||
}
|
||||
|
||||
protected abstract void GetDeformation(out Vector2[,] deformation, out float multiplier);
|
||||
|
||||
public abstract void Update(float deltaTime);
|
||||
|
||||
public static Vector2[,] GetDeformation(IEnumerable<SpriteDeformation> animations, Vector2 scale)
|
||||
{
|
||||
foreach (SpriteDeformation animation in animations)
|
||||
{
|
||||
if (animation.Params.Resolution.X != animation.Deformation.GetLength(0) ||
|
||||
animation.Params.Resolution.Y != animation.Deformation.GetLength(1))
|
||||
{
|
||||
animation.Deformation = new Vector2[animation.Params.Resolution.X, animation.Params.Resolution.Y];
|
||||
}
|
||||
}
|
||||
|
||||
Point resolution = animations.First().Resolution;
|
||||
if (animations.Any(a => a.Resolution != resolution))
|
||||
{
|
||||
DebugConsole.ThrowError("All animations must have the same resolution! Using the lowest resolution.");
|
||||
resolution = animations.OrderBy(anim => anim.Resolution.X + anim.Resolution.Y).First().Resolution;
|
||||
animations.ForEach(a => a.Resolution = resolution);
|
||||
}
|
||||
|
||||
Vector2[,] deformation = new Vector2[resolution.X, resolution.Y];
|
||||
foreach (SpriteDeformation animation in animations)
|
||||
{
|
||||
animation.GetDeformation(out Vector2[,] animDeformation, out float multiplier);
|
||||
|
||||
for (int x = 0; x < resolution.X; x++)
|
||||
{
|
||||
for (int y = 0; y < resolution.Y; y++)
|
||||
{
|
||||
switch (animation.Params.BlendMode)
|
||||
{
|
||||
case DeformationBlendMode.Override:
|
||||
deformation[x,y] = animDeformation[x,y] * scale * multiplier;
|
||||
break;
|
||||
case DeformationBlendMode.Add:
|
||||
deformation[x, y] += animDeformation[x, y] * scale * multiplier;
|
||||
break;
|
||||
case DeformationBlendMode.Multiply:
|
||||
deformation[x, y] *= animDeformation[x, y] * multiplier;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deformation;
|
||||
}
|
||||
|
||||
public virtual void Save(XElement element)
|
||||
{
|
||||
SerializableProperty.SerializeProperties(Params, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user