Client LuaCsForBarotrauma
SpriteDeformation.cs
1 using Microsoft.Xna.Framework;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Xml.Linq;
7 
9 {
11  {
17  [Serialize(-1, IsPropertySaveable.Yes), Editable(minValue: -1, maxValue: 100)]
18  public int Sync
19  {
20  get;
21  private set;
22  }
23 
25  public string Type
26  {
27  get;
28  set;
29  }
30 
33  {
34  get;
35  set;
36  }
37 
38  public string Name => $"Deformation ({Type})";
39 
40  [Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
41  public float Strength { get; private set; }
42 
43  [Serialize(90f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 90)]
44  public float MaxRotation { get; private set; }
45 
47  public bool UseMovementSine { get; set; }
48 
50  public bool StopWhenHostIsDead { get; set; }
51 
53  public bool OnlyInWater { get; set; }
54 
59  public float SineOffset { get; set; }
60 
61  public virtual float Frequency { get; set; } = 1;
62 
63  public Dictionary<Identifier, SerializableProperty> SerializableProperties
64  {
65  get;
66  set;
67  }
68 
72  public static readonly Point ShaderMaxResolution = new Point(15, 15);
73 
74  private Point _resolution;
75  [Serialize("2,2", IsPropertySaveable.Yes)]
76  public Point Resolution
77  {
78  get { return _resolution; }
79  set
80  {
81  if (_resolution == value) { return; }
82  _resolution = value.Clamp(new Point(2, 2), ShaderMaxResolution);
83  }
84  }
85 
86  public SpriteDeformationParams(XElement element)
87  {
89  if (element != null && string.IsNullOrEmpty(Type))
90  {
91  Type = element.GetAttributeString("typename", string.Empty);
92  }
93  }
94  }
95 
96  abstract class SpriteDeformation
97  {
99  {
100  Add,
101  Multiply,
102  Override
103  }
104 
105  public virtual float Phase { get; set; }
106 
107  protected Vector2[,] Deformation { get; private set; }
108 
109  public SpriteDeformationParams Params { get; set; }
110 
111  private static readonly string[] deformationTypes = new string[] { "Inflate", "Custom", "Noise", "BendJoint", "ReactToTriggerers" };
112  public static IEnumerable<string> DeformationTypes
113  {
114  get { return deformationTypes; }
115  }
116 
117  public Point Resolution
118  {
119  get { return Params.Resolution; }
120  set { SetResolution(value); }
121  }
122 
123  public string TypeName => Params.Type;
124 
125  public int Sync => Params.Sync;
126 
127  public static SpriteDeformation Load(string deformationType, string parentDebugName)
128  {
129  return Load(null, deformationType, parentDebugName);
130  }
131  public static SpriteDeformation Load(XElement element, string parentDebugName)
132  {
133  return Load(element, null, parentDebugName);
134  }
135 
136  private static SpriteDeformation Load(XElement element, string deformationType, string parentDebugName)
137  {
138  string typeName = deformationType;
139 
140  if (element != null)
141  {
142  typeName = element.GetAttributeString("typename", null) ?? element.GetAttributeString("type", "");
143  }
144 
145  SpriteDeformation newDeformation = null;
146  switch (typeName.ToLowerInvariant())
147  {
148  case "inflate":
149  newDeformation = new Inflate(element);
150  break;
151  case "custom":
152  newDeformation = new CustomDeformation(element);
153  break;
154  case "noise":
155  newDeformation = new NoiseDeformation(element);
156  break;
157  case "jointbend":
158  case "bendjoint":
159  newDeformation = new JointBendDeformation(element);
160  break;
161  case "reacttotriggerers":
162  return new PositionalDeformation(element);
163  default:
164  if (Enum.TryParse(typeName, out PositionalDeformation.ReactionType reactionType))
165  {
166  newDeformation = new PositionalDeformation(element)
167  {
168  Type = reactionType
169  };
170  }
171  else
172  {
173  DebugConsole.ThrowError("Could not load sprite deformation animation in " + parentDebugName + " - \"" + typeName + "\" is not a valid deformation type.");
174  }
175  break;
176  }
177 
178  if (newDeformation != null)
179  {
180  newDeformation.Params.Type = typeName;
181  }
182  return newDeformation;
183  }
184 
185  protected SpriteDeformation(XElement element, SpriteDeformationParams deformationParams)
186  {
187  this.Params = deformationParams;
188  SerializableProperty.DeserializeProperties(deformationParams, element);
189  Deformation = new Vector2[deformationParams.Resolution.X, deformationParams.Resolution.Y];
190  }
191 
192  public void SetResolution(Point resolution)
193  {
194  Params.Resolution = resolution;
195  Deformation = new Vector2[Params.Resolution.X, Params.Resolution.Y];
196  }
197 
198  protected abstract void GetDeformation(out Vector2[,] deformation, out float multiplier, bool inverse);
199 
200  public abstract void Update(float deltaTime);
201 
202  private static readonly List<int> yValues = new List<int>();
203  public static Vector2[,] GetDeformation(IEnumerable<SpriteDeformation> animations, Vector2 scale, bool inverseY = false)
204  {
205  foreach (SpriteDeformation animation in animations)
206  {
207  if (animation.Params.Resolution.X != animation.Deformation.GetLength(0) ||
208  animation.Params.Resolution.Y != animation.Deformation.GetLength(1))
209  {
210  animation.Deformation = new Vector2[animation.Params.Resolution.X, animation.Params.Resolution.Y];
211  }
212  }
213 
214  Point resolution = animations.First().Resolution;
215  if (animations.Any(a => a.Resolution != resolution))
216  {
217  DebugConsole.ThrowError("All animations must have the same resolution! Using the lowest resolution.");
218  resolution = animations.OrderBy(anim => anim.Resolution.X + anim.Resolution.Y).First().Resolution;
219  animations.ForEach(a => a.Resolution = resolution);
220  }
221 
222  Vector2[,] deformation = new Vector2[resolution.X, resolution.Y];
223  foreach (SpriteDeformation animation in animations)
224  {
225  yValues.Clear();
226  for (int y = 0; y < resolution.Y; y++)
227  {
228  yValues.Add(y);
229  }
230  if (inverseY && animation is CustomDeformation)
231  {
232  yValues.Reverse();
233  }
234  animation.GetDeformation(out Vector2[,] animDeformation, out float multiplier, inverseY);
235  for (int x = 0; x < resolution.X; x++)
236  {
237  for (int y = 0; y < resolution.Y; y++)
238  {
239  switch (animation.Params.BlendMode)
240  {
241  case DeformationBlendMode.Override:
242  deformation[x, yValues[y]] = animDeformation[x, y] * scale * multiplier;
243  break;
244  case DeformationBlendMode.Add:
245  deformation[x, yValues[y]] += animDeformation[x, y] * scale * multiplier;
246  break;
247  case DeformationBlendMode.Multiply:
248  deformation[x, yValues[y]] *= animDeformation[x, y] * multiplier;
249  break;
250  }
251  }
252  }
253  }
254  return deformation;
255  }
256 
257  public virtual void Save(XElement element)
258  {
260  }
261  }
262 }
static Dictionary< Identifier, SerializableProperty > DeserializeProperties(object obj, XElement element=null)
static void SerializeProperties(ISerializableEntity obj, XElement element, bool saveIfDefault=false, bool ignoreEditable=false)
static SpriteDeformation Load(string deformationType, string parentDebugName)
abstract void Update(float deltaTime)
static SpriteDeformation Load(XElement element, string parentDebugName)
abstract void GetDeformation(out Vector2[,] deformation, out float multiplier, bool inverse)
static Vector2[,] GetDeformation(IEnumerable< SpriteDeformation > animations, Vector2 scale, bool inverseY=false)
SpriteDeformation(XElement element, SpriteDeformationParams deformationParams)
float SineOffset
Only used if UseMovementSine is enabled. Multiplier for Pi.
static readonly Point ShaderMaxResolution
Defined in the shader.
Dictionary< Identifier, SerializableProperty > SerializableProperties
int Sync
A negative value means that the deformation is used only by one sprite only (default)....
SpriteDeformation.DeformationBlendMode BlendMode