diff --git a/Raylib-cs/interop/Raylib.cs b/Raylib-cs/interop/Raylib.cs index 6d2daf7..9c80ff3 100644 --- a/Raylib-cs/interop/Raylib.cs +++ b/Raylib-cs/interop/Raylib.cs @@ -1,7 +1,7 @@ -using System; -using System.Numerics; using System.Runtime.InteropServices; +using System.Numerics; using System.Security; +using System; namespace Raylib_cs; diff --git a/Raylib-cs/interop/RaylibExtensions.cs b/Raylib-cs/interop/RaylibExtensions.cs index f94b428..2fae0dd 100644 --- a/Raylib-cs/interop/RaylibExtensions.cs +++ b/Raylib-cs/interop/RaylibExtensions.cs @@ -6,23 +6,6 @@ namespace Raylib_cs; public static class RaylibExtensions { - public static unsafe void SaveFileText(string fileName, string text) - { - using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer(); - using AnsiBuffer textBuffer = text.ToAnsiBuffer(); - Raylib.SaveFileText(fileBuffer.AsPointer(), textBuffer.AsPointer()); - } - - public static unsafe string LoadFileText(string fileName) - { - using AnsiBuffer nameBuffer = fileName.ToAnsiBuffer(); - sbyte* data = Raylib.LoadFileText(nameBuffer.AsPointer()); - //string text = new string(data); - string text = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((System.IntPtr)data); - Raylib.UnloadFileText(data); - return text; - } - #region Rectangle public static void Draw(this Rectangle rectangle, Color color) diff --git a/Raylib-cs/interop/Raymath.cs b/Raylib-cs/interop/Raymath.cs index 0378f2a..b61fa98 100644 --- a/Raylib-cs/interop/Raymath.cs +++ b/Raylib-cs/interop/Raymath.cs @@ -21,7 +21,7 @@ public static unsafe partial class Raymath /// /// Used by DllImport to load the native library /// - public const string NativeLibName = "raylib"; + public const string NativeLibName = Raylib.NativeLibName; /// Clamp float value [DllImport(NativeLibName, CallingConvention = CallingConvention.Cdecl)] diff --git a/Raylib-cs/types/AudioMixed.cs b/Raylib-cs/types/AudioMixed.cs index bf98491..cffc840 100644 --- a/Raylib-cs/types/AudioMixed.cs +++ b/Raylib-cs/types/AudioMixed.cs @@ -1,6 +1,6 @@ -using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System; namespace Raylib_cs; @@ -8,10 +8,8 @@ internal static unsafe class AudioMixed { public static AudioCallback Callback = null; - [UnmanagedCallersOnly(CallConvs = new[] - { - typeof(CallConvCdecl), - })] + [UnmanagedCallersOnly(CallConvs = new Type[] + { typeof(CallConvCdecl) })] public static void Processor(void* buffer, uint frames) { // The buffer is stereo audio, so we need to double our frame count. diff --git a/Raylib-cs/types/Color.cs b/Raylib-cs/types/Color.cs index 4ba3476..b3f9dc0 100644 --- a/Raylib-cs/types/Color.cs +++ b/Raylib-cs/types/Color.cs @@ -1,5 +1,5 @@ -using System; using System.Runtime.InteropServices; +using System; namespace Raylib_cs; @@ -96,11 +96,10 @@ public partial struct Color /// public Color(float r, float g, float b, float a) { - // X = (byte)Math.Clamp(MathF.Round(x * 255), 0f, 255f); - this.R = (byte)((r < 0) ? 0 : ((r > 1) ? 255 : ((r * 255) + .5f))); - this.G = (byte)((g < 0) ? 0 : ((g > 1) ? 255 : ((g * 255) + .5f))); - this.B = (byte)((b < 0) ? 0 : ((b > 1) ? 255 : ((b * 255) + .5f))); - this.A = (byte)((a < 0) ? 0 : ((a > 1) ? 255 : ((a * 255) + .5f))); + this.R = (byte)(Math.Clamp(r, 0.0f, 1.0f) * 255); + this.G = (byte)(Math.Clamp(g, 0.0f, 1.0f) * 255); + this.B = (byte)(Math.Clamp(b, 0.0f, 1.0f) * 255); + this.A = (byte)(Math.Clamp(a, 0.0f, 1.0f) * 255); } /// @@ -110,10 +109,9 @@ public partial struct Color /// public Color(float r, float g, float b) { - // X = (byte)Math.Clamp(MathF.Round(x * 255), 0f, 255f); - this.R = (byte)((r < 0) ? 0 : ((r > 1) ? 255 : ((r * 255) + .5f))); - this.G = (byte)((g < 0) ? 0 : ((g > 1) ? 255 : ((g * 255) + .5f))); - this.B = (byte)((b < 0) ? 0 : ((b > 1) ? 255 : ((b * 255) + .5f))); + this.R = (byte)(Math.Clamp(r, 0.0f, 1.0f) * 255); + this.G = (byte)(Math.Clamp(g, 0.0f, 1.0f) * 255); + this.B = (byte)(Math.Clamp(b, 0.0f, 1.0f) * 255); this.A = 255; } diff --git a/Raylib-cs/types/Image.cs b/Raylib-cs/types/Image.cs index ab15020..ec11acf 100644 --- a/Raylib-cs/types/Image.cs +++ b/Raylib-cs/types/Image.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using System.Numerics; namespace Raylib_cs; @@ -159,4 +160,15 @@ public unsafe partial struct Image /// Data format (PixelFormat type) /// public PixelFormat Format; + + /// + /// Get width and height packed in a Vector2 + /// + public Vector2 Dimensions + { + get + { + return new Vector2(Width, Height); + } + } } diff --git a/Raylib-cs/types/Logging.cs b/Raylib-cs/types/Logging.cs index 2e1789f..d9a1606 100644 --- a/Raylib-cs/types/Logging.cs +++ b/Raylib-cs/types/Logging.cs @@ -42,10 +42,10 @@ struct VaListLinuxX64 /// public static unsafe class Logging { - [UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })] public static unsafe void LogConsole(int msgType, sbyte* text, sbyte* args) { - var message = GetLogMessage(new IntPtr(text), new IntPtr(args)); + string message = GetLogMessage(new IntPtr(text), new IntPtr(args)); Console.WriteLine(message); } @@ -62,13 +62,13 @@ public static unsafe class Logging return LinuxX64LogCallback(format, args); } - var byteLength = VsnPrintf(IntPtr.Zero, UIntPtr.Zero, format, args) + 1; + int byteLength = VsnPrintf(IntPtr.Zero, UIntPtr.Zero, format, args) + 1; if (byteLength <= 1) { return string.Empty; } - var buffer = Marshal.AllocHGlobal(byteLength); + IntPtr buffer = Marshal.AllocHGlobal(byteLength); VsPrintf(buffer, format, args); string result = Marshal.PtrToStringUTF8(buffer); @@ -77,12 +77,12 @@ public static unsafe class Logging return result; } - static string AppleLogCallback(IntPtr format, IntPtr args) + private static string AppleLogCallback(IntPtr format, IntPtr args) { IntPtr buffer = IntPtr.Zero; try { - var count = Native.VasPrintfApple(ref buffer, format, args); + int count = Native.VasPrintfApple(ref buffer, format, args); if (count == -1) { return string.Empty; @@ -98,7 +98,7 @@ public static unsafe class Logging static string LinuxX64LogCallback(IntPtr format, IntPtr args) { // The args pointer cannot be reused between two calls. We need to make a copy of the underlying structure. - var listStructure = Marshal.PtrToStructure(args); + VaListLinuxX64 listStructure = Marshal.PtrToStructure(args); IntPtr listPointer = IntPtr.Zero; int byteLength = 0; string result = ""; @@ -127,7 +127,7 @@ public static unsafe class Logging // https://github.com/dotnet/runtime/issues/51052 static int VsnPrintf(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args) { - var os = Environment.OSVersion; + OperatingSystem os = Environment.OSVersion; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return Native.VsnPrintfWindows(buffer, size, format, args); diff --git a/Raylib-cs/types/Raylib.Utils.cs b/Raylib-cs/types/Raylib.Utils.cs index 0bb4ad4..51c8952 100644 --- a/Raylib-cs/types/Raylib.Utils.cs +++ b/Raylib-cs/types/Raylib.Utils.cs @@ -236,6 +236,21 @@ public static unsafe partial class Raylib return SaveFileData(ansiBuffer.AsPointer(), &data, sizeof(T)); } + /// Save data to file from an unmanaged type + /// True if the operation was successfully + public static CBool SaveFileData(T[] data, string fileName) where T : unmanaged + { + if (data == null || data.Length == 0) + { + return false; + } + fixed (T* ptr = data) + { + using AnsiBuffer ansiBuffer = fileName.ToAnsiBuffer(); + return SaveFileData(ansiBuffer.AsPointer(), ptr, sizeof(T) * data.Length); + } + } + /// Load file data as byte array (read) public static byte* LoadFileData(string fileName, ref int bytesRead) { @@ -275,9 +290,9 @@ public static unsafe partial class Raylib FilePathList filePathList = LoadDroppedFiles(); string[] files = new string[filePathList.Count]; - for (int i = 0; i < filePathList.Count; i++) + for (uint i = 0; i < filePathList.Count; i++) { - files[i] = Marshal.PtrToStringUTF8((IntPtr)filePathList.Paths[i]); + files[i] = filePathList[i]; } UnloadDroppedFiles(filePathList); @@ -1361,10 +1376,7 @@ public static unsafe partial class Raylib /// /// Load music stream from managed memory, fileType refers to extension: i.e. ".wav" /// - public static Music LoadMusicStreamFromMemory( - string fileType, - byte[] fileData - ) + public static Music LoadMusicStreamFromMemory(string fileType, byte[] fileData) { using AnsiBuffer fileTypeNative = fileType.ToAnsiBuffer(); @@ -1479,4 +1491,74 @@ public static unsafe partial class Raylib { return new string(GetWorkingDirectory()); } + + /// + /// Load a sequence of random numbers, store them and return them but not before unloading them. + /// + /// Amount of random numbers to load + /// Minimum random value + /// Maximum random value + /// An array filled with the random numbers + public static int[] GetRandomSequence(uint count, int min, int max) + { + int temp = min; + min = Math.Min(min, max); + max = Math.Max(temp, max); + int* sequence = LoadRandomSequence(count, min, max); + int[] output = new int[count]; + //Marshal.Copy((IntPtr)sequence, output, 0, count); + for (uint i = 0; i < count; i++) + { + output[i] = sequence[i]; + } + UnloadRandomSequence(sequence); + return output; + } + + /// + /// Load a sequence of random numbers, store them and return them but not before unloading them. + /// + /// Amount of random numbers to load + /// Minimum random value + /// Maximum random value + /// An array filled with the random numbers + public static float[] GetRandomSequence(uint count, float min, float max) + { + float temp = min; + min = Math.Min(min, max); + max = Math.Max(temp, max); + const int maxi = 100000; + int* sequence = LoadRandomSequence(count, 0, maxi); + float[] output = new float[count]; + for (uint i = 0; i < count; i++) + { + int val = sequence[i]; + float norm = (float)val / (float)maxi; + output[i] = Raymath.Lerp(min, max, norm); + } + return output; + } + + /// + /// Create a file in the specified path to save the specified text + /// + public static void SaveFileText(string fileName, string text) + { + using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer(); + using AnsiBuffer textBuffer = text.ToAnsiBuffer(); + SaveFileText(fileBuffer.AsPointer(), textBuffer.AsPointer()); + } + + /// + /// Loads text from a file, reads it, saves it, unloads the file, and returns the loaded text. + /// + /// The text content of the file on the given path + public static string LoadFileText(string fileName) + { + using AnsiBuffer nameBuffer = fileName.ToAnsiBuffer(); + sbyte* data = LoadFileText(nameBuffer.AsPointer()); + string text = new string(data); + UnloadFileText(data); + return text; + } } diff --git a/Raylib-cs/types/native/CBool.cs b/Raylib-cs/types/native/CBool.cs index 93e9408..cd7ec2b 100644 --- a/Raylib-cs/types/native/CBool.cs +++ b/Raylib-cs/types/native/CBool.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace Raylib_cs; @@ -13,8 +12,8 @@ public readonly struct CBool * which can be later implicitely cast onto any type during usage. * * It is wise to note that C booleans are any numeric value, but allocating an - * Int64 for every CBool instance is.. well, wildly memory-inefficient. Yes, the - * process is basically treated as a 0-cost instantiation, but it's better to rely + * Int64 (long) for every CBool instance is.. well, wildly memory-inefficient. Yes, + * the process is basically treated as a 0-cost instantiation, but it's better to rely * on explicit motivation than to blindly trust the runtime judgement on its memory * management. * @@ -30,7 +29,7 @@ public readonly struct CBool { this.Value = (sbyte)(value ? 1 : 0); } - public CBool(Int64 value) + public CBool(long value) { this.Value = (sbyte)(value != 0 ? 1 : 0); } @@ -45,20 +44,20 @@ public readonly struct CBool // Allows for CBools to be implicitely assigned to a native boolean variable. public static implicit operator bool(CBool x) { - return x.Value != 0 ? true : false; + return x.Value != 0; } // Native -> CBool // Allows native booleans to be implicitely constructed into CBools while passing parameters. public static implicit operator CBool(bool x) { - return new CBool { Value = (sbyte)(x ? 1 : 0) }; + return new CBool(x); } // Same goes for integer numeric values (any value, so an Int64 is used). - public static implicit operator CBool(Int64 x) + public static implicit operator CBool(long x) { - return new CBool { Value = (sbyte)(x != 0 ? 1 : 0) }; + return new CBool(x); } /* Arithmetic overloads diff --git a/Raylib-cs/types/native/FilePathList.cs b/Raylib-cs/types/native/FilePathList.cs index b75dc1c..6aa1517 100644 --- a/Raylib-cs/types/native/FilePathList.cs +++ b/Raylib-cs/types/native/FilePathList.cs @@ -22,4 +22,12 @@ public unsafe struct FilePathList /// Filepaths entries /// public byte** Paths; + + public string this[uint i] + { + get + { + return Marshal.PtrToStringUTF8((System.IntPtr)Paths[i]); + } + } } diff --git a/Raylib-cs/types/native/Utf8Buffer.cs b/Raylib-cs/types/native/Utf8Buffer.cs index f77bff7..3acb824 100644 --- a/Raylib-cs/types/native/Utf8Buffer.cs +++ b/Raylib-cs/types/native/Utf8Buffer.cs @@ -41,10 +41,10 @@ public static class Utf8StringUtils return null; } - var length = Encoding.UTF8.GetByteCount(text); + int length = Encoding.UTF8.GetByteCount(text); - var byteArray = new byte[length + 1]; - var wrote = Encoding.UTF8.GetBytes(text, 0, text.Length, byteArray, 0); + byte[] byteArray = new byte[length + 1]; + int wrote = Encoding.UTF8.GetBytes(text, 0, text.Length, byteArray, 0); byteArray[wrote] = 0; return byteArray;