diff --git a/LemonUI/Elements/BaseElement.cs b/LemonUI/Elements/BaseElement.cs
index 208911b..d68def8 100644
--- a/LemonUI/Elements/BaseElement.cs
+++ b/LemonUI/Elements/BaseElement.cs
@@ -34,12 +34,9 @@ public abstract class BaseElement : I2Dimensional
///
/// The Position of the drawable.
///
- public PointF Position
+ public virtual PointF Position
{
- get
- {
- return literalPosition;
- }
+ get => literalPosition;
set
{
literalPosition = value;
@@ -49,12 +46,9 @@ public PointF Position
///
/// The Size of the drawable.
///
- public SizeF Size
+ public virtual SizeF Size
{
- get
- {
- return literalSize;
- }
+ get => literalSize;
set
{
literalSize = value;
@@ -64,11 +58,11 @@ public SizeF Size
///
/// The Color of the drawable.
///
- public Color Color { get; set; } = Color.FromArgb(255, 255, 255, 255);
+ public virtual Color Color { get; set; } = Color.FromArgb(255, 255, 255, 255);
///
/// The rotation of the drawable.
///
- public float Heading { get; set; } = 0;
+ public virtual float Heading { get; set; } = 0;
#endregion
diff --git a/LemonUI/Elements/ScaledAnim.cs b/LemonUI/Elements/ScaledAnim.cs
new file mode 100644
index 0000000..0a46989
--- /dev/null
+++ b/LemonUI/Elements/ScaledAnim.cs
@@ -0,0 +1,148 @@
+#if ALTV
+using AltV.Net.Client;
+#elif FIVEM
+using CitizenFX.Core;
+#elif RAGEMP
+using RAGE.Game;
+#elif RPH
+using Rage.Native;
+#elif SHVDN3 || SHVDNC
+using GTA;
+#endif
+using System;
+using System.Drawing;
+
+namespace LemonUI.Elements
+{
+ ///
+ /// A scaled animation using YTD files with all of the frames.
+ ///
+ public class ScaledAnim : ScaledTexture
+ {
+ #region Fields
+
+ private float frameRate;
+ private int start = 0;
+ private int duration;
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// The total number of frames per second.
+ ///
+ public float FrameRate
+ {
+ get => frameRate;
+ set
+ {
+ if (value <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), "The Frame Rate can't be equal or lower to zero.");
+ }
+
+ frameRate = value;
+ }
+ }
+ ///
+ /// The duration of the animation in milliseconds.
+ ///
+ public int Duration
+ {
+ get => duration;
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), "The duration can't be under zero.");
+ }
+
+ duration = value;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Creates a new dictionary based animation.
+ ///
+ /// The texture dictionary (YTD) to use.
+ public ScaledAnim(string dict) : this(dict, PointF.Empty, SizeF.Empty)
+ {
+ }
+ ///
+ /// Creates a new dictionary based animation.
+ ///
+ /// The texture dictionary (YTD) to use.
+ /// The size of the animation.
+ public ScaledAnim(string dict, SizeF size) : this(dict, PointF.Empty, size)
+ {
+ }
+ ///
+ /// Creates a new dictionary based animation.
+ ///
+ /// The texture dictionary (YTD) to use.
+ /// The position of the animation.
+ /// The size of the animation.
+ public ScaledAnim(string dict, PointF pos, SizeF size) : base(pos, size, dict, string.Empty)
+ {
+ Dictionary = dict ?? throw new ArgumentNullException(nameof(dict));
+ }
+
+ #endregion
+
+ #region Functions
+
+ ///
+ /// Draws the animation.
+ ///
+ public override void Draw()
+ {
+ if (Duration <= 0)
+ {
+ return;
+ }
+
+#if ALTV
+ int time = Alt.Natives.GetGameTimer();
+#elif RAGEMP
+ int time = Misc.GetGameTimer();
+#elif RPH
+ int time = NativeFunction.CallByHash(0x9CD27B0045628463);
+#elif FIVEM || SHVDN3 || SHVDNC
+ int time = Game.GameTime;
+#endif
+
+ int end = start + Duration;
+
+ if (start == 0 || end <= time)
+ {
+ start = time;
+ }
+
+ float progress = (time - (float)start) / Duration;
+ int totalFrames = (int)((duration / 1000.0f) * frameRate);
+ int currentFrame = (int)(totalFrames * progress) + 1;
+
+ if (progress < 0)
+ {
+ currentFrame = 1;
+ start = time;
+ }
+ else if (currentFrame >= totalFrames)
+ {
+ currentFrame = totalFrames;
+ start = time;
+ }
+
+ Texture = currentFrame.ToString();
+
+ base.Draw();
+ }
+
+ #endregion
+ }
+}