diff --git a/LemonUI/Elements/BaseElement.cs b/LemonUI/Elements/BaseElement.cs
index 55222526..208911b8 100644
--- a/LemonUI/Elements/BaseElement.cs
+++ b/LemonUI/Elements/BaseElement.cs
@@ -1,5 +1,5 @@
-using LemonUI.Extensions;
using System.Drawing;
+using LemonUI.Tools;
namespace LemonUI.Elements
{
diff --git a/LemonUI/Elements/ScaledText.cs b/LemonUI/Elements/ScaledText.cs
index 481c0e99..05fffb2f 100644
--- a/LemonUI/Elements/ScaledText.cs
+++ b/LemonUI/Elements/ScaledText.cs
@@ -16,7 +16,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Text;
-using LemonUI.Extensions;
+using LemonUI.Tools;
namespace LemonUI.Elements
{
@@ -37,9 +37,9 @@ public class ScaledText : IText
#region Fields
///
- /// The absolute 1080p based screen position.
+ /// The scaled 1080p based screen position.
///
- private PointF absolutePosition = PointF.Empty;
+ private PointF scaledPosition = PointF.Empty;
///
/// The relative 0-1 relative position.
///
@@ -74,10 +74,10 @@ public class ScaledText : IText
///
public PointF Position
{
- get => absolutePosition;
+ get => scaledPosition;
set
{
- absolutePosition = value;
+ scaledPosition = value;
relativePosition = value.ToRelative();
}
}
@@ -150,23 +150,23 @@ public float Width
#if FIVEM
API.BeginTextCommandWidth("CELL_EMAIL_BCON");
Add();
- return API.EndTextCommandGetWidth(true) * 1f.ToXAbsolute();
+ return API.EndTextCommandGetWidth(true) * 1f.ToXScaled();
#elif ALTV
Alt.Natives.BeginTextCommandGetScreenWidthOfDisplayText("CELL_EMAIL_BCON");
Add();
- return Alt.Natives.EndTextCommandGetScreenWidthOfDisplayText(true) * 1f.ToXAbsolute();
+ return Alt.Natives.EndTextCommandGetScreenWidthOfDisplayText(true) * 1f.ToXScaled();
#elif RAGEMP
Invoker.Invoke(Natives.BeginTextCommandWidth, "CELL_EMAIL_BCON");
Add();
- return Invoker.Invoke(Natives.EndTextCommandGetWidth) * 1f.ToXAbsolute();
+ return Invoker.Invoke(Natives.EndTextCommandGetWidth) * 1f.ToXScaled();
#elif RPH
NativeFunction.CallByHash(0x54CE8AC98E120CAB, "CELL_EMAIL_BCON");
Add();
- return NativeFunction.CallByHash(0x85F061DA64ED2F67, true) * 1f.ToXAbsolute();
+ return NativeFunction.CallByHash(0x85F061DA64ED2F67, true) * 1f.ToXScaled();
#elif SHVDN3 || SHVDNC
Function.Call(Hash.BEGIN_TEXT_COMMAND_GET_SCREEN_WIDTH_OF_DISPLAY_TEXT, "CELL_EMAIL_BCON");
Add();
- return Function.Call(Hash.END_TEXT_COMMAND_GET_SCREEN_WIDTH_OF_DISPLAY_TEXT, true) * 1f.ToXAbsolute();
+ return Function.Call(Hash.END_TEXT_COMMAND_GET_SCREEN_WIDTH_OF_DISPLAY_TEXT, true) * 1f.ToXScaled();
#endif
}
}
@@ -505,7 +505,7 @@ private void Slice()
public void Recalculate()
{
// Do the normal Size and Position recalculation
- relativePosition = absolutePosition.ToRelative();
+ relativePosition = scaledPosition.ToRelative();
// And recalculate the word wrap if necessary
if (internalWrap <= 0)
{
diff --git a/LemonUI/Extensions/FloatExtensions.cs b/LemonUI/Extensions/FloatExtensions.cs
index 81bb74e6..ddc7340a 100644
--- a/LemonUI/Extensions/FloatExtensions.cs
+++ b/LemonUI/Extensions/FloatExtensions.cs
@@ -1,53 +1,36 @@
+using System;
+
namespace LemonUI.Extensions
{
///
/// Extensions for the float class.
///
+ [Obsolete("Please use LemonUI.Tools.Extensions instead.", true)]
public static class FloatExtensions
{
- #region Extensions
-
///
- /// Converts an absolute X or Width float to a relative one.
+ /// Converts a scaled X or Width float to a relative one.
///
/// The float to convert.
/// A relative float between 0 and 1.
- public static float ToXRelative(this float fin)
- {
- Screen.ToRelative(fin, 0, out float fout, out _);
- return fout;
- }
+ public static float ToXRelative(this float fin) => Tools.Extensions.ToXRelative(fin);
///
- /// Converts an absolute Y or Height float to a relative one.
+ /// Converts a scaled Y or Height float to a relative one.
///
/// The float to convert.
/// A relative float between 0 and 1.
- public static float ToYRelative(this float fin)
- {
- Screen.ToRelative(0, fin, out _, out float fout);
- return fout;
- }
+ public static float ToYRelative(this float fin) => Tools.Extensions.ToYRelative(fin);
///
- /// Converts an relative X or Width float to an absolute one.
+ /// Converts an relative X or Width float to an scaled one.
///
/// The float to convert.
- /// An absolute float.
- public static float ToXAbsolute(this float fin)
- {
- Screen.ToAbsolute(fin, 0, out float fout, out _);
- return fout;
- }
+ /// A scaled float.
+ public static float ToXAbsolute(this float fin) => Tools.Extensions.ToXScaled(fin);
///
- /// Converts an relative Y or Height float to an absolute one.
+ /// Converts an relative Y or Height float to an scaled one.
///
/// The float to convert.
- /// An absolute float.
- public static float ToYAbsolute(this float fin)
- {
- Screen.ToAbsolute(0, fin, out _, out float fout);
- return fout;
- }
-
- #endregion
+ /// A scaled float.
+ public static float ToYAbsolute(this float fin) => Tools.Extensions.ToYScaled(fin);
}
}
diff --git a/LemonUI/Extensions/PointExtensions.cs b/LemonUI/Extensions/PointExtensions.cs
index 5b81adf5..5f0c2673 100644
--- a/LemonUI/Extensions/PointExtensions.cs
+++ b/LemonUI/Extensions/PointExtensions.cs
@@ -1,3 +1,4 @@
+using System;
using System.Drawing;
namespace LemonUI.Extensions
@@ -5,31 +6,20 @@ namespace LemonUI.Extensions
///
/// Extensions for the Point and PointF classes.
///
+ [Obsolete("Please use LemonUI.Tools.Extensions instead.", true)]
public static class PointExtensions
{
- #region Extensions
-
///
- /// Converts an absolute 1080-based position into a relative one.
+ /// Converts a scaled 1080-based position into a relative one.
///
- /// The absolute PointF.
+ /// The scaled PointF.
/// A new PointF with relative values.
- public static PointF ToRelative(this PointF point)
- {
- Screen.ToRelative(point.X, point.Y, out float x, out float y);
- return new PointF(x, y);
- }
+ public static PointF ToRelative(this PointF point) => Tools.Extensions.ToRelative(point);
///
- /// Converts a normalized 0-1 position into an absolute one.
+ /// Converts a normalized 0-1 position into a scaled one.
///
/// The relative PointF.
- /// A new PointF with absolute values.
- public static PointF ToAbsolute(this PointF point)
- {
- Screen.ToAbsolute(point.X, point.Y, out float x, out float y);
- return new PointF(x, y);
- }
-
- #endregion
+ /// A new PointF with scaled values.
+ public static PointF ToAbsolute(this PointF point) => Tools.Extensions.ToScaled(point);
}
}
diff --git a/LemonUI/Extensions/SizeExtensions.cs b/LemonUI/Extensions/SizeExtensions.cs
index e2a893e1..0660a346 100644
--- a/LemonUI/Extensions/SizeExtensions.cs
+++ b/LemonUI/Extensions/SizeExtensions.cs
@@ -1,3 +1,4 @@
+using System;
using System.Drawing;
namespace LemonUI.Extensions
@@ -5,31 +6,20 @@ namespace LemonUI.Extensions
///
/// Extensions for the Size and SizeF classes.
///
+ [Obsolete("Please use LemonUI.Tools.Extensions instead.", true)]
public static class SizeExtensions
{
- #region Extensions
-
///
- /// Converts an absolute 1080-based size into a relative one.
+ /// Converts a scaled 1080-based size into a relative one.
///
- /// The absolute SizeF.
+ /// The scaled SizeF.
/// A new SizeF with relative values.
- public static SizeF ToRelative(this SizeF size)
- {
- Screen.ToRelative(size.Width, size.Height, out float width, out float height);
- return new SizeF(width, height);
- }
+ public static SizeF ToRelative(this SizeF size) => Tools.Extensions.ToRelative(size);
///
- /// Converts a normalized 0-1 size into an absolute one.
+ /// Converts a normalized 0-1 size into a scaled one.
///
/// The relative SizeF.
- /// A new SizeF with absolute values.
- public static SizeF ToAbsolute(this SizeF size)
- {
- Screen.ToAbsolute(size.Width, size.Height, out float width, out float height);
- return new SizeF(width, height);
- }
-
- #endregion
+ /// A new SizeF with scaled values.
+ public static SizeF ToAbsolute(this SizeF size) => Tools.Extensions.ToScaled(size);
}
}
diff --git a/LemonUI/Menus/NativeGridPanel.cs b/LemonUI/Menus/NativeGridPanel.cs
index 4605b353..afc3a787 100644
--- a/LemonUI/Menus/NativeGridPanel.cs
+++ b/LemonUI/Menus/NativeGridPanel.cs
@@ -12,13 +12,12 @@
using Control = Rage.GameControl;
#elif SHVDN3 || SHVDNC
using GTA;
-using GTA.Native;
using GTA.UI;
#endif
using LemonUI.Elements;
-using LemonUI.Extensions;
using System;
using System.Drawing;
+using LemonUI.Tools;
namespace LemonUI.Menus
{
@@ -290,16 +289,16 @@ public override void Process()
if (!Controls.IsUsingController)
{
- if (Screen.IsCursorInArea(grid.Position, grid.Size) && Controls.IsPressed(Control.CursorAccept))
+ if (GameScreen.IsCursorInArea(grid.Position, grid.Size) && Controls.IsPressed(Control.CursorAccept))
{
- PointF cursor = Screen.CursorPositionRelative;
- PointF pos = innerPosition.ToRelative();
+ PointF cursor = GameScreen.Cursor;
+ PointF pos = innerPosition;
PointF start = new PointF(cursor.X - pos.X, cursor.Y - pos.Y);
- SizeF size = innerSize.ToRelative();
+ SizeF size = innerSize;
- x = start.X / size.Width;
- y = start.Y / size.Height;
+ x = (start.X / size.Width).ToXRelative();
+ y = (start.Y / size.Height).ToYRelative();
}
else
{
diff --git a/LemonUI/Menus/NativeItem.cs b/LemonUI/Menus/NativeItem.cs
index 61b7999a..a36969b7 100644
--- a/LemonUI/Menus/NativeItem.cs
+++ b/LemonUI/Menus/NativeItem.cs
@@ -11,6 +11,7 @@
using LemonUI.Elements;
using System;
using System.Drawing;
+using LemonUI.Tools;
namespace LemonUI.Menus
{
@@ -230,7 +231,7 @@ public ColorSet Colors
///
/// If this item is being hovered.
///
- public bool IsHovered => Screen.IsCursorInArea(background.Position, background.Size);
+ public bool IsHovered => GameScreen.IsCursorInArea(background.Position, background.Size);
#endregion
diff --git a/LemonUI/Menus/NativeListItem{T}.cs b/LemonUI/Menus/NativeListItem{T}.cs
index ee2a11dd..7c5d3b7c 100644
--- a/LemonUI/Menus/NativeListItem{T}.cs
+++ b/LemonUI/Menus/NativeListItem{T}.cs
@@ -73,7 +73,7 @@ public T SelectedItem
{
if (Items.Count == 0)
{
- throw new InvalidOperationException("There are no available items.");
+ return;
}
int newIndex = Items.IndexOf(value);
diff --git a/LemonUI/Menus/NativeMenu.cs b/LemonUI/Menus/NativeMenu.cs
index f6837732..c9412946 100644
--- a/LemonUI/Menus/NativeMenu.cs
+++ b/LemonUI/Menus/NativeMenu.cs
@@ -26,13 +26,13 @@
using Font = GTA.UI.Font;
#endif
using LemonUI.Elements;
-using LemonUI.Extensions;
using LemonUI.Scaleform;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
+using LemonUI.Tools;
namespace LemonUI.Menus
{
@@ -950,11 +950,10 @@ public void ResetCursor()
const float extraX = 35;
const float extraY = 325;
- // Get the correct desired position of the cursor as relative
PointF pos = PointF.Empty;
if (SafeZoneAware)
{
- Screen.SetElementAlignment(Alignment, GFXAlignment.Top);
+ SafeZone.SetAlignment(Alignment, GFXAlignment.Top);
float x = 0;
switch (Alignment)
{
@@ -965,8 +964,8 @@ public void ResetCursor()
x = Offset.X - Width - extraX;
break;
}
- pos = Screen.GetRealPosition(x, Offset.Y + extraY).ToRelative();
- Screen.ResetElementAlignment();
+ pos = SafeZone.GetSafePosition(x, Offset.Y + extraY).ToRelative();
+ SafeZone.ResetAlignment();
}
else
{
@@ -977,7 +976,7 @@ public void ResetCursor()
x = Offset.X + Width + extraX;
break;
case Alignment.Right:
- x = 1f.ToXAbsolute() - Offset.X - Width - extraX;
+ x = 1f.ToXScaled() - Offset.X - Width - extraX;
break;
}
pos = new PointF(x, Offset.Y + extraY).ToRelative();
@@ -1004,7 +1003,7 @@ private void UpdateItems()
PointF pos;
if (SafeZoneAware)
{
- Screen.SetElementAlignment(Alignment, GFXAlignment.Top);
+ SafeZone.SetAlignment(Alignment, GFXAlignment.Top);
float x = 0;
switch (Alignment)
{
@@ -1015,8 +1014,8 @@ private void UpdateItems()
x = Offset.X - Width;
break;
}
- pos = Screen.GetRealPosition(x, Offset.Y);
- Screen.ResetElementAlignment();
+ pos = SafeZone.GetSafePosition(x, Offset.Y);
+ SafeZone.ResetAlignment();
}
else
{
@@ -1027,7 +1026,7 @@ private void UpdateItems()
x = Offset.X;
break;
case Alignment.Right:
- x = 1f.ToXAbsolute() - Width - Offset.X;
+ x = 1f.ToXScaled() - Width - Offset.X;
break;
}
pos = new PointF(x, Offset.Y);
@@ -1208,18 +1207,12 @@ private void ProcessControls()
if (UseMouse && !Controls.IsUsingController)
{
// Enable the mouse cursor
-#if FIVEM || SHVDN3 || SHVDNC || ALTV
- Screen.ShowCursorThisFrame();
-#elif RAGEMP
- Invoker.Invoke(Natives.ShowCursorThisFrame);
-#elif RPH
- NativeFunction.CallByHash(0xAAE7CE1D63167423);
-#endif
+ GameScreen.ShowCursorThisFrame();
// If the camera should be rotated when the cursor is on the left and right sections of the screen, do so
if (RotateCamera)
{
- if (Screen.IsCursorInArea(PointF.Empty, searchAreaSize))
+ if (GameScreen.IsCursorInArea(PointF.Empty, searchAreaSize))
{
#if FIVEM || SHVDN3 || SHVDNC
GameplayCamera.RelativeHeading += 5;
@@ -1233,7 +1226,7 @@ private void ProcessControls()
Camera.RenderingCamera.Heading += 5;
#endif
}
- else if (Screen.IsCursorInArea(searchAreaRight, searchAreaSize))
+ else if (GameScreen.IsCursorInArea(searchAreaRight, searchAreaSize))
{
#if FIVEM || SHVDN3 || SHVDNC
GameplayCamera.RelativeHeading -= 5;
@@ -1259,7 +1252,7 @@ private void ProcessControls()
if (item == selectedItem && item is NativeSlidableItem slidable)
{
// If the right arrow was pressed, go to the right
- if (Screen.IsCursorInArea(slidable.RightArrow.Position, slidable.RightArrow.Size))
+ if (GameScreen.IsCursorInArea(slidable.RightArrow.Position, slidable.RightArrow.Size))
{
if (item.Enabled)
{
@@ -1273,7 +1266,7 @@ private void ProcessControls()
return;
}
// If the user pressed the left arrow, go to the right
- else if (Screen.IsCursorInArea(slidable.LeftArrow.Position, slidable.LeftArrow.Size))
+ else if (GameScreen.IsCursorInArea(slidable.LeftArrow.Position, slidable.LeftArrow.Size))
{
if (item.Enabled)
{
@@ -1289,7 +1282,7 @@ private void ProcessControls()
}
// If the cursor is inside of the selection rectangle
- if (Screen.IsCursorInArea(item.title.Position.X - itemOffsetX, item.title.Position.Y - itemOffsetY, Width, itemHeight))
+ if (GameScreen.IsCursorInArea(item.title.Position.X - itemOffsetX, item.title.Position.Y - itemOffsetY, Width, itemHeight))
{
// If the item is selected, activate it
if (item == selectedItem)
@@ -1688,9 +1681,8 @@ public virtual void Recalculate()
x = Offset.X - Width;
break;
}
- Screen.SetElementAlignment(Alignment, GFXAlignment.Top);
- pos = Screen.GetRealPosition(x, Offset.Y);
- Screen.ResetElementAlignment();
+
+ pos = SafeZone.GetPositionAt(new PointF(x, Offset.Y), Alignment, GFXAlignment.Top);
}
else
{
@@ -1701,7 +1693,7 @@ public virtual void Recalculate()
x = Offset.X;
break;
case Alignment.Right:
- x = 1f.ToXAbsolute() - Width - Offset.X;
+ x = 1f.ToXScaled() - Width - Offset.X;
break;
}
pos = new PointF(x, Offset.Y);
@@ -1742,7 +1734,7 @@ public virtual void Recalculate()
descriptionText.WordWrap = width - posXDescTxt;
// Set the right size of the rotation
- searchAreaRight = new PointF(1f.ToXAbsolute() - 30, 0);
+ searchAreaRight = new PointF(1f.ToXScaled() - 30, 0);
// Then, continue with an item update
UpdateItems();
diff --git a/LemonUI/ObjectPool.cs b/LemonUI/ObjectPool.cs
index 4405dd47..cf4dbacc 100644
--- a/LemonUI/ObjectPool.cs
+++ b/LemonUI/ObjectPool.cs
@@ -15,6 +15,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
+using LemonUI.Tools;
namespace LemonUI
{
@@ -28,32 +29,11 @@ public class ObjectPool : IEnumerable
///
/// The last known resolution by the object pool.
///
-#if FIVEM
- private SizeF lastKnownResolution = CitizenFX.Core.UI.Screen.Resolution;
-#elif ALTV
- private SizeF lastKnownResolution = Screen.Resolution;
-#elif RAGEMP
- private SizeF lastKnownResolution = new SizeF(Game.ScreenResolution.Width, Game.ScreenResolution.Height);
-#elif RPH
- private SizeF lastKnownResolution = Game.Resolution;
-#elif SHVDN3 || SHVDNC
- private SizeF lastKnownResolution = GTA.UI.Screen.Resolution;
-#endif
+ private SizeF lastKnownResolution = GameScreen.AbsoluteResolution;
///
/// The last know Safezone size.
///
-#if FIVEM
- private float lastKnownSafezone = API.GetSafeZoneSize();
-#elif ALTV
- private float lastKnownSafezone = Alt.Natives.GetSafeZoneSize();
-#elif RAGEMP
- private float lastKnownSafezone = Invoker.Invoke(Natives.GetSafeZoneSize);
-#elif RPH
- private float lastKnownSafezone = NativeFunction.CallByHash(0xBAF107B6BB2C97F0);
-#elif SHVDN3 || SHVDNC
- private float lastKnownSafezone = Function.Call(Hash.GET_SAFE_ZONE_SIZE);
-#endif
-
+ private float lastKnownSafezone = SafeZone.Size;
///
/// The list of processable objects.
///
@@ -104,18 +84,7 @@ public bool AreAnyVisible
private void DetectResolutionChanges()
{
// Get the current resolution
-#if FIVEM
- SizeF resolution = CitizenFX.Core.UI.Screen.Resolution;
-#elif ALTV
- SizeF resolution = Screen.Resolution;
-#elif RAGEMP
- ScreenResolutionType raw = Game.ScreenResolution;
- SizeF resolution = new SizeF(raw.Width, raw.Height);
-#elif RPH
- SizeF resolution = Game.Resolution;
-#elif SHVDN3 || SHVDNC
- SizeF resolution = GTA.UI.Screen.Resolution;
-#endif
+ SizeF resolution = GameScreen.AbsoluteResolution;
// If the old res does not matches the current one
if (lastKnownResolution != resolution)
{
@@ -133,18 +102,7 @@ private void DetectResolutionChanges()
private void DetectSafezoneChanges()
{
// Get the current Safezone size
-#if FIVEM
- float safezone = API.GetSafeZoneSize();
-#elif ALTV
- float safezone = Alt.Natives.GetSafeZoneSize();
-#elif RAGEMP
- float safezone = Invoker.Invoke(Natives.GetSafeZoneSize);
-#elif RPH
- float safezone = NativeFunction.CallByHash(0xBAF107B6BB2C97F0);
-#elif SHVDN3 || SHVDNC
- float safezone = Function.Call(Hash.GET_SAFE_ZONE_SIZE);
-#endif
-
+ float safezone = SafeZone.Size;
// If is not the same as the last one
if (lastKnownSafezone != safezone)
{
diff --git a/LemonUI/Screen.cs b/LemonUI/Screen.cs
index 27acfe79..b7c893d8 100644
--- a/LemonUI/Screen.cs
+++ b/LemonUI/Screen.cs
@@ -16,15 +16,16 @@
using AltV.Net.Client;
using LemonUI.Elements;
#endif
-using LemonUI.Extensions;
using System;
using System.Drawing;
+using LemonUI.Tools;
namespace LemonUI
{
///
/// Contains a set of tools to work with the screen information.
///
+ [Obsolete("Use the LemonUI.Tools and LemonUI.Math namespaces.")]
public static class Screen
{
#region Properties
@@ -32,65 +33,17 @@ public static class Screen
///
/// The Aspect Ratio of the screen resolution.
///
- public static float AspectRatio
- {
- get
- {
-#if FIVEM
- return API.GetAspectRatio(false);
-#elif RAGEMP
- return Invoker.Invoke(Natives.GetAspectRatio);
-#elif RPH
- return NativeFunction.CallByHash(0xF1307EF624A80D87, false);
-#elif SHVDN3 || SHVDNC
- return Function.Call(Hash.GET_ASPECT_RATIO, false);
-#elif ALTV
- return Alt.Natives.GetAspectRatio(false);
-#endif
- }
- }
-
+ public static float AspectRatio => GameScreen.AspectRatio;
#if ALTV
///
- /// Gets the actual Screen resolution the game is being rendered at
+ /// Gets the actual Screen resolution the game is being rendered at.
///
- public static Size Resolution
- {
- get
- {
- int height = 0, width = 0;
- Alt.Natives.GetActualScreenResolution(ref width, ref height);
- return new Size(width, height);
- }
- }
+ public static Size Resolution => GameScreen.AbsoluteResolution.ToSize();
#endif
-
///
/// The location of the cursor on screen between 0 and 1.
///
- public static PointF CursorPositionRelative
- {
- get
- {
-#if FIVEM
- float cursorX = API.GetControlNormal(0, (int)Control.CursorX);
- float cursorY = API.GetControlNormal(0, (int)Control.CursorY);
-#elif ALTV
- float cursorX = Alt.Natives.GetControlNormal(0, (int)Control.CursorX);
- float cursorY = Alt.Natives.GetControlNormal(0, (int)Control.CursorY);
-#elif RAGEMP
- float cursorX = Invoker.Invoke(Natives.GetControlNormal, 0, (int)Control.CursorX);
- float cursorY = Invoker.Invoke(Natives.GetControlNormal, 0, (int)Control.CursorY);
-#elif RPH
- float cursorX = NativeFunction.CallByHash(0xEC3C9B8D5327B563, 0, (int)Control.CursorX);
- float cursorY = NativeFunction.CallByHash(0xEC3C9B8D5327B563, 0, (int)Control.CursorY);
-#elif SHVDN3 || SHVDNC
- float cursorX = Function.Call(Hash.GET_CONTROL_NORMAL, 0, (int)Control.CursorX);
- float cursorY = Function.Call(Hash.GET_CONTROL_NORMAL, 0, (int)Control.CursorY);
-#endif
- return new PointF(cursorX, cursorY);
- }
- }
+ public static PointF CursorPositionRelative => GameScreen.Cursor.ToRelative();
#endregion
@@ -105,11 +58,8 @@ public static PointF CursorPositionRelative
/// The value of Y scaled to 1080p.
public static void ToAbsolute(float relativeX, float relativeY, out float absoluteX, out float absoluteY)
{
- // Get the real width based on the aspect ratio
- float width = 1080f * AspectRatio;
- // And save the correct values
- absoluteX = width * relativeX;
- absoluteY = 1080f * relativeY;
+ absoluteX = relativeX.ToXScaled();
+ absoluteY = relativeY.ToYScaled();
}
///
/// Converts a 1080p-based resolution into relative values.
@@ -120,11 +70,8 @@ public static void ToAbsolute(float relativeX, float relativeY, out float absolu
/// The value of Y converted to relative.
public static void ToRelative(float absoluteX, float absoluteY, out float relativeX, out float relativeY)
{
- // Get the real width based on the aspect ratio
- float width = 1080f * AspectRatio;
- // And save the correct values
- relativeX = absoluteX / width;
- relativeY = absoluteY / 1080f;
+ relativeX = absoluteX.ToXRelative();
+ relativeY = absoluteY.ToYRelative();
}
///
/// Checks if the cursor is inside of the specified area.
@@ -149,16 +96,9 @@ public static void ToRelative(float absoluteX, float absoluteY, out float relati
/// if the cursor is in the specified bounds, otherwise.
public static bool IsCursorInArea(float x, float y, float width, float height)
{
- PointF cursor = CursorPositionRelative;
-
- ToRelative(width, height, out float realWidth, out float realHeight);
-
+ // intentionally kept this way to avoid breaking backwards compatibility
PointF realPos = GetRealPosition(x, y).ToRelative();
-
- bool isX = cursor.X >= realPos.X && cursor.X <= realPos.X + realWidth;
- bool isY = cursor.Y > realPos.Y && cursor.Y < realPos.Y + realHeight;
-
- return isX && isY;
+ return GameScreen.IsCursorInArea(realPos.X, realPos.Y, width, height);
}
///
/// Converts the specified position into one that is aware of .
@@ -172,128 +112,27 @@ public static bool IsCursorInArea(float x, float y, float width, float height)
/// The 1080p based X position.
/// The 1080p based Y position.
/// A new 1080p based position that is aware of the the Alignment.
- public static PointF GetRealPosition(float x, float y)
- {
- // Convert the resolution to relative
- ToRelative(x, y, out float relativeX, out float relativeY);
- // Request the real location of the position
- float realX = 0, realY = 0;
-#if FIVEM
- API.GetScriptGfxPosition(relativeX, relativeY, ref realX, ref realY);
-#elif ALTV
- Alt.Natives.GetScriptGfxAlignPosition(relativeX, relativeY, ref realX, ref realY);
-#elif RAGEMP
- FloatReference argX = new FloatReference();
- FloatReference argY = new FloatReference();
- Invoker.Invoke(0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY);
- realX = argX.Value;
- realY = argY.Value;
-#elif RPH
- using (NativePointer argX = new NativePointer(4))
- using (NativePointer argY = new NativePointer(4))
- {
- NativeFunction.CallByHash(0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY);
- realX = argX.GetValue();
- realY = argY.GetValue();
- }
-#elif SHVDN3 || SHVDNC
- using (OutputArgument argX = new OutputArgument())
- using (OutputArgument argY = new OutputArgument())
- {
- Function.Call((Hash)0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY); // _GET_SCRIPT_GFX_POSITION
- realX = argX.GetResult();
- realY = argY.GetResult();
- }
-#endif
- // And return it converted to absolute
- ToAbsolute(realX, realY, out float absoluteX, out float absoluteY);
- return new PointF(absoluteX, absoluteY);
- }
+ public static PointF GetRealPosition(float x, float y) => SafeZone.GetSafePosition(x, y);
///
/// Shows the cursor during the current game frame.
///
- public static void ShowCursorThisFrame()
- {
-#if FIVEM
- API.SetMouseCursorActiveThisFrame();
-#elif ALTV
- Alt.Natives.SetMouseCursorThisFrame();
-#elif RAGEMP
- Invoker.Invoke(0xAAE7CE1D63167423);
-#elif RPH
- NativeFunction.CallByHash(0xAAE7CE1D63167423);
-#elif SHVDN3 || SHVDNC
- Function.Call(Hash.SET_MOUSE_CURSOR_THIS_FRAME);
-#endif
- }
+ public static void ShowCursorThisFrame() => GameScreen.ShowCursorThisFrame();
///
/// Sets the alignment of game elements like , and .
///
/// The Horizontal alignment of the items.
/// The vertical alignment of the items.
- public static void SetElementAlignment(Alignment horizontal, GFXAlignment vertical)
- {
- // If the enum value is not correct, raise an exception
- if (!Enum.IsDefined(typeof(Alignment), horizontal))
- {
- throw new ArgumentException("Alignment is not one of the allowed values (Left, Right, Center).", nameof(horizontal));
- }
-
- // Otherwise, just call the correct function
- switch (horizontal)
- {
- case Alignment.Left:
- SetElementAlignment(GFXAlignment.Left, vertical);
- break;
- case Alignment.Right:
- SetElementAlignment(GFXAlignment.Right, vertical);
- break;
- case Alignment.Center:
- SetElementAlignment(GFXAlignment.Right, vertical);
- break;
- }
- }
+ public static void SetElementAlignment(Alignment horizontal, GFXAlignment vertical) => SafeZone.SetAlignment(horizontal, vertical);
///
/// Sets the alignment of game elements like , and .
///
/// The Horizontal alignment of the items.
/// The vertical alignment of the items.
- public static void SetElementAlignment(GFXAlignment horizontal, GFXAlignment vertical)
- {
-#if FIVEM
- API.SetScriptGfxAlign((int)horizontal, (int)vertical);
- API.SetScriptGfxAlignParams(0, 0, 0, 0);
-#elif ALTV
- Alt.Natives.SetScriptGfxAlign((int)horizontal, (int)vertical);
- Alt.Natives.SetScriptGfxAlignParams(0, 0, 0, 0);
-#elif RAGEMP
- Invoker.Invoke(0xB8A850F20A067EB6, (int)horizontal, (int)vertical);
- Invoker.Invoke(0xF5A2C681787E579D, 0, 0, 0, 0);
-#elif RPH
- NativeFunction.CallByHash(0xB8A850F20A067EB6, (int)horizontal, (int)vertical);
- NativeFunction.CallByHash(0xF5A2C681787E579D, 0, 0, 0, 0);
-#elif SHVDN3 || SHVDNC
- Function.Call(Hash.SET_SCRIPT_GFX_ALIGN, (int)horizontal, (int)vertical);
- Function.Call(Hash.SET_SCRIPT_GFX_ALIGN_PARAMS, 0, 0, 0, 0);
-#endif
- }
+ public static void SetElementAlignment(GFXAlignment horizontal, GFXAlignment vertical) => SafeZone.SetAlignment(horizontal, vertical);
///
/// Resets the alignment of the game elements.
///
- public static void ResetElementAlignment()
- {
-#if FIVEM
- API.ResetScriptGfxAlign();
-#elif ALTV
- Alt.Natives.ResetScriptGfxAlign();
-#elif RAGEMP
- Invoker.Invoke(0xE3A3DB414A373DAB);
-#elif RPH
- NativeFunction.CallByHash(0xE3A3DB414A373DAB);
-#elif SHVDN3 || SHVDNC
- Function.Call(Hash.RESET_SCRIPT_GFX_ALIGN);
-#endif
- }
+ public static void ResetElementAlignment() => SafeZone.ResetAlignment();
#endregion
}
diff --git a/LemonUI/TimerBars/TimerBarCollection.cs b/LemonUI/TimerBars/TimerBarCollection.cs
index e5b88107..cb7de5df 100644
--- a/LemonUI/TimerBars/TimerBarCollection.cs
+++ b/LemonUI/TimerBars/TimerBarCollection.cs
@@ -14,6 +14,7 @@
using System.Collections.Generic;
using System.Drawing;
using LemonUI.Elements;
+using LemonUI.Tools;
namespace LemonUI.TimerBars
{
@@ -139,9 +140,7 @@ public void Remove(Func func)
///
public void Recalculate()
{
- Screen.SetElementAlignment(GFXAlignment.Right, GFXAlignment.Bottom);
- PointF pos = Screen.GetRealPosition(PointF.Empty);
- Screen.ResetElementAlignment();
+ PointF pos = SafeZone.BottomRight;
pos.X += offset.X;
pos.Y += offset.Y;
diff --git a/LemonUI/Tools/Extensions.cs b/LemonUI/Tools/Extensions.cs
new file mode 100644
index 00000000..4d9c7e88
--- /dev/null
+++ b/LemonUI/Tools/Extensions.cs
@@ -0,0 +1,73 @@
+using System.Drawing;
+
+namespace LemonUI.Tools
+{
+ ///
+ /// Extensions for converting values between relative and scaled.
+ ///
+ public static class Extensions
+ {
+ #region Float
+
+ ///
+ /// Converts the scaled X or Width to a relative one.
+ ///
+ /// The value to convert.
+ /// A relative float between 0 and 1.
+ public static float ToXRelative(this float x) => x / (1080f * GameScreen.AspectRatio);
+ ///
+ /// Converts the scaled Y or Height to a relative one.
+ ///
+ /// The value to convert.
+ /// A relative float between 0 and 1.
+ public static float ToYRelative(this float y) => y / 1080f;
+ ///
+ /// Converts the relative X or Width float to a scaled one.
+ ///
+ /// The float to convert.
+ /// A scaled float.
+ public static float ToXScaled(this float x) => (1080f * GameScreen.AspectRatio) * x;
+ ///
+ /// Converts the relative Y or Height float to a scaled one.
+ ///
+ /// The float to convert.
+ /// A scaled float.
+ public static float ToYScaled(this float y) => 1080f * y;
+
+ #endregion
+
+ #region PointF
+
+ ///
+ /// Converts a scaled 1080p-based position into a relative one.
+ ///
+ /// The scaled PointF.
+ /// A new PointF with relative values.
+ public static PointF ToRelative(this PointF point) => new PointF(point.X.ToXRelative(), point.Y.ToYRelative());
+ ///
+ /// Converts a relative 0-1 position into a scaled one.
+ ///
+ /// The relative PointF.
+ /// A new PointF with scaled values.
+ public static PointF ToScaled(this PointF point) => new PointF(point.X.ToXScaled(), point.Y.ToYScaled());
+
+ #endregion
+
+ #region SizeF
+
+ ///
+ /// Converts a scaled 1080p-based position into a relative one.
+ ///
+ /// The scaled SizeF.
+ /// A new SizeF with relative values.
+ public static SizeF ToRelative(this SizeF size) => new SizeF(size.Width.ToXRelative(), size.Height.ToYRelative());
+ ///
+ /// Converts a relative 0-1 position into a scaled one.
+ ///
+ /// The relative SizeF.
+ /// A new SizeF with scaled values.
+ public static SizeF ToScaled(this SizeF size) => new SizeF(size.Width.ToXScaled(), size.Height.ToYScaled());
+
+ #endregion
+ }
+}
diff --git a/LemonUI/Tools/GameScreen.cs b/LemonUI/Tools/GameScreen.cs
new file mode 100644
index 00000000..4315cf57
--- /dev/null
+++ b/LemonUI/Tools/GameScreen.cs
@@ -0,0 +1,147 @@
+#if FIVEM
+using CitizenFX.Core;
+using CitizenFX.Core.Native;
+using CitizenFX.Core.UI;
+#elif RAGEMP
+using RAGE.Game;
+using RAGE.NUI;
+#elif RPH
+using Rage;
+using Rage.Native;
+using Control = Rage.GameControl;
+#elif SHVDN3 || SHVDNC
+using GTA;
+using GTA.Native;
+#elif ALTV
+using AltV.Net.Client;
+using LemonUI.Elements;
+#endif
+using System.Drawing;
+
+namespace LemonUI.Tools
+{
+ ///
+ /// The screen of the game being rendered.
+ ///
+ public static class GameScreen
+ {
+ #region Properties
+
+ ///
+ /// Gets the actual Screen resolution the game is being rendered at.
+ ///
+ public static SizeF AbsoluteResolution
+ {
+ get
+ {
+#if ALTV
+ int height = 0, width = 0;
+ Alt.Natives.GetActualScreenResolution(ref width, ref height);
+ return new SizeF(width, height);
+#elif FIVEM
+ return CitizenFX.Core.UI.Screen.Resolution;
+#elif RAGEMP
+ ScreenResolutionType raw = Game.ScreenResolution;
+ return new SizeF(raw.Width, raw.Height);
+#elif RPH
+ return Game.Resolution;
+#elif SHVDN3 || SHVDNC
+ return GTA.UI.Screen.Resolution;
+#endif
+ }
+ }
+ ///
+ /// The Aspect Ratio of the screen.
+ ///
+ public static float AspectRatio
+ {
+ get
+ {
+#if FIVEM
+ return API.GetAspectRatio(false);
+#elif RAGEMP
+ return Invoker.Invoke(Natives.GetAspectRatio);
+#elif RPH
+ return NativeFunction.CallByHash(0xF1307EF624A80D87, false);
+#elif SHVDN3 || SHVDNC
+ return Function.Call(Hash.GET_ASPECT_RATIO, false);
+#elif ALTV
+ return Alt.Natives.GetAspectRatio(false);
+#endif
+ }
+ }
+ ///
+ /// The location of the cursor on screen between 0 and 1.
+ ///
+ public static PointF Cursor
+ {
+ get
+ {
+#if FIVEM
+ float cursorX = API.GetControlNormal(0, (int)Control.CursorX);
+ float cursorY = API.GetControlNormal(0, (int)Control.CursorY);
+#elif ALTV
+ float cursorX = Alt.Natives.GetControlNormal(0, (int)Control.CursorX);
+ float cursorY = Alt.Natives.GetControlNormal(0, (int)Control.CursorY);
+#elif RAGEMP
+ float cursorX = Invoker.Invoke(Natives.GetControlNormal, 0, (int)Control.CursorX);
+ float cursorY = Invoker.Invoke(Natives.GetControlNormal, 0, (int)Control.CursorY);
+#elif RPH
+ float cursorX = NativeFunction.CallByHash(0xEC3C9B8D5327B563, 0, (int)Control.CursorX);
+ float cursorY = NativeFunction.CallByHash(0xEC3C9B8D5327B563, 0, (int)Control.CursorY);
+#elif SHVDN3 || SHVDNC
+ float cursorX = Function.Call(Hash.GET_CONTROL_NORMAL, 0, (int)Control.CursorX);
+ float cursorY = Function.Call(Hash.GET_CONTROL_NORMAL, 0, (int)Control.CursorY);
+#endif
+ return new PointF(cursorX.ToXScaled(), cursorY.ToYScaled());
+ }
+ }
+
+ #endregion
+
+ #region Functions
+
+ ///
+ /// Checks if the cursor is inside of the scaled area.
+ ///
+ /// The scaled position.
+ /// The scaled size of the area.
+ /// if the cursor is in the specified bounds, otherwise.
+ public static bool IsCursorInArea(PointF pos, SizeF size) => IsCursorInArea(pos.X, pos.Y, size.Width, size.Height);
+ ///
+ /// Checks if the cursor is inside of the scaled area.
+ ///
+ /// The scaled X position.
+ /// The scaled Y position.
+ /// The scaled width of the area.
+ /// The scaled height of the area.
+ /// if the cursor is in the specified bounds, otherwise.
+ public static bool IsCursorInArea(float x, float y, float width, float height)
+ {
+ PointF cursorPosition = Cursor;
+
+ bool isX = cursorPosition.X >= x && cursorPosition.X <= x + width;
+ bool isY = cursorPosition.Y > y && cursorPosition.Y < y + height;
+ return isX && isY;
+ }
+ ///
+ /// Shows the cursor during the current game frame.
+ ///
+ public static void ShowCursorThisFrame()
+ {
+#if FIVEM
+ API.SetMouseCursorActiveThisFrame();
+#elif ALTV
+ Alt.Natives.SetMouseCursorThisFrame();
+#elif RAGEMP
+ Invoker.Invoke(0xAAE7CE1D63167423);
+#elif RPH
+ NativeFunction.CallByHash(0xAAE7CE1D63167423);
+#elif SHVDN3 || SHVDNC
+ Function.Call(Hash.SET_MOUSE_CURSOR_THIS_FRAME);
+#endif
+ }
+
+ #endregion
+ }
+}
diff --git a/LemonUI/Tools/SafeZone.cs b/LemonUI/Tools/SafeZone.cs
new file mode 100644
index 00000000..4ddfa8d3
--- /dev/null
+++ b/LemonUI/Tools/SafeZone.cs
@@ -0,0 +1,209 @@
+#if ALTV
+using AltV.Net.Client;
+#elif RAGEMP
+using RAGE.Game;
+#elif FIVEM
+using CitizenFX.Core.Native;
+using CitizenFX.Core.UI;
+#elif RPH
+using Rage.Native;
+#elif SHVDN3 || SHVDNC
+using GTA.Native;
+using GTA.UI;
+#endif
+using System;
+using System.Drawing;
+
+namespace LemonUI.Tools
+{
+ ///
+ /// Tools for changing, resetting and retrieving the Safe Zone of the game.
+ ///
+ public static class SafeZone
+ {
+ #region Properties
+
+ ///
+ /// The size of the safe zone.
+ ///
+ ///
+ /// This property should not be used to manually calculate the safe zone. Use to get the safe zone size.
+ ///
+ public static float Size
+ {
+ get
+ {
+#if ALTV
+ return Alt.Natives.GetSafeZoneSize();
+#elif FIVEM
+ return API.GetSafeZoneSize();
+#elif RAGEMP
+ return Invoker.Invoke(Natives.GetSafeZoneSize);
+#elif RPH
+ return NativeFunction.CallByHash(0xBAF107B6BB2C97F0);
+#elif SHVDN3 || SHVDNC
+ return Function.Call(Hash.GET_SAFE_ZONE_SIZE);
+#endif
+ }
+ }
+ ///
+ /// The top left corner after the safe zone.
+ ///
+ public static PointF TopLeft => GetPositionAt(PointF.Empty, GFXAlignment.Left, GFXAlignment.Top);
+ ///
+ /// The top right corner after the safe zone.
+ ///
+ public static PointF TopRight => GetPositionAt(PointF.Empty, GFXAlignment.Right, GFXAlignment.Top);
+ ///
+ /// The bottom left corner after the safe zone.
+ ///
+ public static PointF BottomLeft => GetPositionAt(PointF.Empty, GFXAlignment.Left, GFXAlignment.Bottom);
+ ///
+ /// The bottom right corner after the safe zone.
+ ///
+ public static PointF BottomRight => GetPositionAt(PointF.Empty, GFXAlignment.Right, GFXAlignment.Bottom);
+
+ #endregion
+
+ #region Tools
+
+ private static GFXAlignment AlignmentToGFXAlignment(Alignment alignment)
+ {
+ switch (alignment)
+ {
+ case Alignment.Left:
+ return GFXAlignment.Left;
+ case Alignment.Right:
+ return GFXAlignment.Right;
+ case Alignment.Center:
+ return GFXAlignment.Center;
+ default:
+ throw new ArgumentException("Alignment is not one of the allowed values (Left, Right, Center).", nameof(alignment));
+ }
+ }
+
+ #endregion
+
+ #region Functions
+
+ ///
+ /// Converts the specified position into one that is aware of the safe zone.
+ ///
+ /// The original 1080p based position.
+ /// A new 1080p based position that is aware of the the Alignment.
+ public static PointF GetSafePosition(PointF og) => GetSafePosition(og.X, og.Y);
+ ///
+ /// Converts the specified position into one that is aware of .
+ ///
+ /// The 1080p based X position.
+ /// The 1080p based Y position.
+ /// A new 1080p based position that is aware of the the Alignment.
+ public static PointF GetSafePosition(float x, float y)
+ {
+ float relativeX = x.ToXRelative();
+ float relativeY = y.ToYRelative();
+
+ float realX = 0, realY = 0;
+#if FIVEM
+ API.GetScriptGfxPosition(relativeX, relativeY, ref realX, ref realY);
+#elif ALTV
+ Alt.Natives.GetScriptGfxAlignPosition(relativeX, relativeY, ref realX, ref realY);
+#elif RAGEMP
+ FloatReference argX = new FloatReference();
+ FloatReference argY = new FloatReference();
+ Invoker.Invoke(0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY);
+ realX = argX.Value;
+ realY = argY.Value;
+#elif RPH
+ using (NativePointer argX = new NativePointer(4))
+ using (NativePointer argY = new NativePointer(4))
+ {
+ NativeFunction.CallByHash(0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY);
+ realX = argX.GetValue();
+ realY = argY.GetValue();
+ }
+#elif SHVDN3 || SHVDNC
+ using (OutputArgument argX = new OutputArgument())
+ using (OutputArgument argY = new OutputArgument())
+ {
+ Function.Call((Hash)0x6DD8F5AA635EB4B2, relativeX, relativeY, argX, argY); // _GET_SCRIPT_GFX_POSITION
+ realX = argX.GetResult();
+ realY = argY.GetResult();
+ }
+#endif
+
+ return new PointF(realX.ToXScaled(), realY.ToYScaled());
+ }
+ ///
+ /// Sets the alignment for the safe zone.
+ ///
+ /// The Horizontal alignment of the items.
+ /// The vertical alignment of the items.
+ public static void SetAlignment(Alignment horizontal, GFXAlignment vertical) => SetAlignment(AlignmentToGFXAlignment(horizontal), vertical);
+ ///
+ /// Sets the alignment for the safe zone.
+ ///
+ /// The Horizontal alignment of the items.
+ /// The vertical alignment of the items.
+ public static void SetAlignment(GFXAlignment horizontal, GFXAlignment vertical)
+ {
+#if FIVEM
+ API.SetScriptGfxAlign((int)horizontal, (int)vertical);
+ API.SetScriptGfxAlignParams(0, 0, 0, 0);
+#elif ALTV
+ Alt.Natives.SetScriptGfxAlign((int)horizontal, (int)vertical);
+ Alt.Natives.SetScriptGfxAlignParams(0, 0, 0, 0);
+#elif RAGEMP
+ Invoker.Invoke(0xB8A850F20A067EB6, (int)horizontal, (int)vertical);
+ Invoker.Invoke(0xF5A2C681787E579D, 0, 0, 0, 0);
+#elif RPH
+ NativeFunction.CallByHash(0xB8A850F20A067EB6, (int)horizontal, (int)vertical);
+ NativeFunction.CallByHash(0xF5A2C681787E579D, 0, 0, 0, 0);
+#elif SHVDN3 || SHVDNC
+ Function.Call(Hash.SET_SCRIPT_GFX_ALIGN, (int)horizontal, (int)vertical);
+ Function.Call(Hash.SET_SCRIPT_GFX_ALIGN_PARAMS, 0, 0, 0, 0);
+#endif
+ }
+ ///
+ /// Resets the alignment of the safe zone.
+ ///
+ public static void ResetAlignment()
+ {
+#if FIVEM
+ API.ResetScriptGfxAlign();
+#elif ALTV
+ Alt.Natives.ResetScriptGfxAlign();
+#elif RAGEMP
+ Invoker.Invoke(0xE3A3DB414A373DAB);
+#elif RPH
+ NativeFunction.CallByHash(0xE3A3DB414A373DAB);
+#elif SHVDN3 || SHVDNC
+ Function.Call(Hash.RESET_SCRIPT_GFX_ALIGN);
+#endif
+ }
+ ///
+ /// Gets the specified position with the specified safe zone alignment.
+ ///
+ /// The position to get.
+ /// The horizontal alignment.
+ /// The vertical alignment.
+ /// The safe zone alignment.
+ public static PointF GetPositionAt(PointF position, Alignment horizontal, GFXAlignment vertical) => GetPositionAt(position, AlignmentToGFXAlignment(horizontal), vertical);
+ ///
+ /// Gets the specified position with the specified safe zone alignment.
+ ///
+ /// The position to get.
+ /// The horizontal alignment.
+ /// The vertical alignment.
+ /// The scaled safe zone alignment.
+ public static PointF GetPositionAt(PointF position, GFXAlignment horizontal, GFXAlignment vertical)
+ {
+ SetAlignment(horizontal, vertical);
+ PointF pos = GetSafePosition(position);
+ ResetAlignment();
+ return pos;
+ }
+
+ #endregion
+ }
+}
diff --git a/README.md b/README.md
index d41a970c..fd16fca9 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# LemonUI
[![GitHub Actions][actions-img]][actions-url] [![NuGet][nuget-img-2]][nuget-url-2] [![NuGet][nuget-img-3]][nuget-url-3] [![NuGet][nuget-img-f]][nuget-url-f] [![NuGet][nuget-img-r]][nuget-url-r] [![Patreon][patreon-img]][patreon-url] [![PayPal][paypal-img]][paypal-url] [![Discord][discord-img]][discord-url]
+# LemonUI
[![GitHub Actions][actions-img]][actions-url] [![NuGet][nuget-img-3]][nuget-url-3] [![NuGet][nuget-img-f]][nuget-url-f] [![NuGet][nuget-img-r]][nuget-url-r] [![NuGet][nuget-img-a]][nuget-url-a] [![Patreon][patreon-img]][patreon-url] [![PayPal][paypal-img]][paypal-url] [![Discord][discord-img]][discord-url]
LemonUI is a framework for creating UI systems in Grand Theft Auto V that is compatible with FiveM, RageMP, RagePluginHook ScriptHookVDotNet 2 and ScriptHookVDotNet 3. It allows you to create UI Elements with a NativeUI-like style, or you can also create your own UI System from scratch via the resolution-independant classes for Text, Rectangles and Textures.
@@ -37,29 +37,23 @@ Copy all of the files from the **RPH** folder inside of the compressed file to t
### ScriptHookVDotNet 2 and ScriptHookVDotNet 3
-**PLEASE NOTE THAT THE LAST VERSION THAT SUPPORTED SHVDN2 WAS 1.5.2. [You can download it here]().**
+**PLEASE NOTE THAT THE LAST VERSION THAT SUPPORTED SHVDN2 WAS 1.5.2. [You can download it here](https://github.com/LemonUIbyLemon/LemonUI/releases/tag/v1.5.2).**
Copy all of the files from the **SHVDN2** and/or **SHVDN3** folder(s) inside of the compressed file to your **scripts** directory.
-### Developers
-
-Add any of the NuGet packages linked above and start working in your IDE.
-
-If you are using RagePluginHook or ScriptHookVDotNet, you can disable the copy of the dll in your IDE so your users always have to use the latest version available.
-
-If you are using RageMP, you will need to download the latest release and copy **LemonUI.RageMP.cs** to you client solution.
-
## Usage
Once installed, the mods that require LemonUI will start working.
-If you are a developer, check the [wiki](https://github.com/LemonUIbyLemon/LemonUI/wiki) for information to implement LemonUI in your mod.
+## Developers
+
+Check the [Quick Start guide](https://github.com/LemonUIbyLemon/LemonUI/wiki/Quick-Start) to learn how to use LemonUI in your project.
+
+If you would like to make changes to the code, clone the repo, restore the packages and open the solution in your favorite IDE.
[actions-img]: https://img.shields.io/github/actions/workflow/status/LemonUIbyLemon/LemonUI/main.yml?branch=master&label=actions
[actions-url]: https://github.com/LemonUIbyLemon/LemonUI/actions
-[nuget-img-2]: https://img.shields.io/nuget/v/LemonUI.SHVDN2?label=nuget%20%28shvdn%202%29
-[nuget-url-2]: https://www.nuget.org/packages/LemonUI.SHVDN2/
-[nuget-img-3]: https://img.shields.io/nuget/v/LemonUI.SHVDN3?label=nuget%20%28shvdn%203%29
+[nuget-img-3]: https://img.shields.io/nuget/v/LemonUI.SHVDN3?label=nuget%20%28shvdn3%29
[nuget-url-3]: https://www.nuget.org/packages/LemonUI.SHVDN3/
[nuget-img-f]: https://img.shields.io/nuget/v/LemonUI.FiveM?label=nuget%20%28fivem%29
[nuget-url-f]: https://www.nuget.org/packages/LemonUI.FiveM/
@@ -67,6 +61,8 @@ If you are a developer, check the [wiki](https://github.com/LemonUIbyLemon/Lemon
[nuget-url-m]: https://www.nuget.org/packages/LemonUI.RageMP/
[nuget-img-r]: https://img.shields.io/nuget/v/LemonUI.RagePluginHook?label=nuget%20%28rph%29
[nuget-url-r]: https://www.nuget.org/packages/LemonUI.RagePluginHook/
+[nuget-img-a]: https://img.shields.io/nuget/v/LemonUI.AltV?label=nuget%20%28altv%29
+[nuget-url-a]: https://www.nuget.org/packages/LemonUI.AltV/
[patreon-img]: https://img.shields.io/badge/support-patreon-FF424D.svg
[patreon-url]: https://www.patreon.com/lemonchan
[paypal-img]: https://img.shields.io/badge/support-paypal-0079C1.svg