2
0
mirror of https://github.com/raylib-cs/raylib-cs synced 2025-10-13 04:51:53 -04:00

Explicit core types and autonomous types. (#304)

* All the "var" variables were changed to explicit types on the raylib class
* "MakeDirectory" overload, and string version of "GetApplicationDirectory" and "GetWorkingDirectory" methods
* Added "Dimensions" property to "Texture2D"
* New overloads for the "LoadFileData" and "SaveFileData" methods
* Raymath's const "NativeLibName" is now referencing to "Raylib.NativeLibName"
* Color constructors are more readable
* Added "Dimensions" property to "Image"
* Changed all the "var" for explicit types on the "Logging" class
* Changed "Int64" for "long" on CBool, and using constructor on the operators instead setting the value manually
* Added indexer to "FilePathLists"
* Changed all "var" for explicit types on "Utf8Buffer"
* New "GetRandomSequence" method overloads in "Raylib.Utils" acepting "int" and "float"
* Added new extension "byte.Lerp"
* Added new extension "Log" for "TraceLogLevel"
* Constructors on Color no longer just truncate the float value, but also round it (+ 0.5f)
* New static method on Color, "Color.Lerp"
* Added static method "FromHSV" to Color
* Added new getter method "GetHSV" on Color
* Added index security on the FilePathList indexer
* Added Rectangle extension
* Added "MoveTowards" extensions to RaylibExtensions
* Added "TranslateLocal" and "TranslateGlobal" to Transform
* Removed unnecessary "partial" declarations
* Updating calls and docs
* Moved the "AudioCallback" delegate into the "AudioMixed.cs" File
* Properties and structs marked as read-only on the "Model.cs" file
* Updated the "README.md" to mentions Raylib-cs targets net6.0 and net8.0 (and also explicitly added that the
"STAThread" attribute comes from the "System" namespace)
* Added a few sizing utils to "Rectangle"
* Added "GetScreenCenter" to "Raylib.Utils"
This commit is contained in:
Matorio
2025-09-21 03:09:38 -05:00
committed by GitHub
parent ca4e760d60
commit 75aabd1cc0
34 changed files with 602 additions and 196 deletions

View File

@@ -10,7 +10,8 @@ C# bindings for raylib, a simple and easy-to-use library to learn videogames pro
[![GitHub stars](https://img.shields.io/github/stars/raylib-cs/raylib-cs?style=social)](https://github.com/raylib-cs/raylib-cs/stargazers) [![GitHub stars](https://img.shields.io/github/stars/raylib-cs/raylib-cs?style=social)](https://github.com/raylib-cs/raylib-cs/stargazers)
[![Build](https://github.com/raylib-cs/raylib-cs/workflows/Build/badge.svg)](https://github.com/raylib-cs/raylib-cs/actions?query=workflow%3ABuild) [![Build](https://github.com/raylib-cs/raylib-cs/workflows/Build/badge.svg)](https://github.com/raylib-cs/raylib-cs/actions?query=workflow%3ABuild)
Raylib-cs targets net6.0 and uses the [official 5.5 release](https://github.com/raysan5/raylib/releases/tag/5.5) to build the native libraries. Raylib-cs targets net6.0 net8.0 and uses the [official 5.5 release](https://github.com/raysan5/raylib/releases/tag/5.5)
to build the native libraries.
## Status ## Status
@@ -37,8 +38,8 @@ dotnet add package Raylib-cs
If you need to edit Raylib-cs source then you will need to add the bindings as a project (see below). If you need to edit Raylib-cs source then you will need to add the bindings as a project (see below).
If you are new to using NuGet (or you've forgotten) and are trying to run the above command in the command prompt, If you are new to using NuGet (or you've forgotten) and are trying to run the above command in the command prompt,
remember that you need to be *inside the intended project directory* (not just inside the solution directory) otherwise remember that you need to be *inside the intended project directory* (not just inside the solution directory)
the command won't work. otherwise the command won't work.
## Installation - Manual ## Installation - Manual
@@ -60,10 +61,10 @@ using Raylib_cs;
namespace HelloWorld; namespace HelloWorld;
class Program internal static class Program
{ {
// STAThread is required if you deploy using NativeAOT on Windows - See https://github.com/raylib-cs/raylib-cs/issues/301 // STAThread is required if you deploy using NativeAOT on Windows - See https://github.com/raylib-cs/raylib-cs/issues/301
[STAThread] [System.STAThread]
public static void Main() public static void Main()
{ {
Raylib.InitWindow(800, 480, "Hello World"); Raylib.InitWindow(800, 480, "Hello World");

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks> <TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems> <EnableDefaultItems>false</EnableDefaultItems>
@@ -49,9 +49,6 @@
<ItemGroup> <ItemGroup>
<Compile Include="interop\*.cs" /> <Compile Include="interop\*.cs" />
<Compile Include="types\*.cs" /> <Compile Include="types\*.cs" />
<Compile Include="types\native\CBool.cs" /> <Compile Include="types\native\*.cs" />
<Compile Include="types\native\AnsiBuffer.cs" />
<Compile Include="types\native\Utf8Buffer.cs" />
<Compile Include="types\native\FilePathList.cs" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,7 +1,7 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Numerics;
using System.Security; using System.Security;
using System;
namespace Raylib_cs; namespace Raylib_cs;

View File

@@ -1,5 +1,5 @@
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Numerics;
using System.Security; using System.Security;
namespace Raylib_cs; namespace Raylib_cs;
@@ -21,7 +21,7 @@ public static unsafe partial class Raymath
/// <summary> /// <summary>
/// Used by DllImport to load the native library /// Used by DllImport to load the native library
/// </summary> /// </summary>
public const string NativeLibName = "raylib"; public const string NativeLibName = Raylib.NativeLibName;
/// <summary>Clamp float value</summary> /// <summary>Clamp float value</summary>
[DllImport(NativeLibName, CallingConvention = CallingConvention.Cdecl)] [DllImport(NativeLibName, CallingConvention = CallingConvention.Cdecl)]
@@ -37,12 +37,9 @@ public static unsafe partial class Raymath
/// <summary>Remap input value within input range to output range</summary> /// <summary>Remap input value within input range to output range</summary>
[DllImport(NativeLibName, CallingConvention = CallingConvention.Cdecl)] [DllImport(NativeLibName, CallingConvention = CallingConvention.Cdecl)]
public static extern float Remap( public static extern float Remap(float value,
float value, float inputStart, float inputEnd,
float inputStart, float outputStart, float outputEnd
float inputEnd,
float outputStart,
float outputEnd
); );
/// <summary>Wrap input value from min to max</summary> /// <summary>Wrap input value from min to max</summary>

View File

@@ -1,10 +0,0 @@
using System;
namespace Raylib_cs;
/// <summary>
/// Audio stream processor.
/// Used with Raylib.AttachAudioMixedProcessor()
/// and Raylib.DetachAudioMixedProcessor()
/// </summary>
public delegate void AudioCallback<T>(Span<T> buffer);

View File

@@ -1,17 +1,22 @@
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System;
namespace Raylib_cs; namespace Raylib_cs;
/// <summary>
/// Audio stream processor.
/// Used with <see cref="Raylib.AttachAudioMixedProcessor(AudioCallback{float})"/>
/// and <see cref="Raylib.DetachAudioMixedProcessor(AudioCallback{float})"/>
/// </summary>
public delegate void AudioCallback<T>(Span<T> buffer);
internal static unsafe class AudioMixed internal static unsafe class AudioMixed
{ {
public static AudioCallback<float> Callback = null; public static AudioCallback<float> Callback = null;
[UnmanagedCallersOnly(CallConvs = new[] [UnmanagedCallersOnly(CallConvs = new Type[]
{ { typeof(CallConvCdecl) })]
typeof(CallConvCdecl),
})]
public static void Processor(void* buffer, uint frames) public static void Processor(void* buffer, uint frames)
{ {
// The buffer is stereo audio, so we need to double our frame count. // The buffer is stereo audio, so we need to double our frame count.

View File

@@ -8,7 +8,7 @@ namespace Raylib_cs;
/// NOTE: Useful to create custom audio streams not bound to a specific file /// NOTE: Useful to create custom audio streams not bound to a specific file
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct AudioStream public struct AudioStream
{ {
// TODO: convert // TODO: convert
/// <summary> /// <summary>

View File

@@ -31,5 +31,5 @@ public unsafe struct AutomationEventList
public AutomationEvent* Events; public AutomationEvent* Events;
/// <inheritdoc cref="Events"/> /// <inheritdoc cref="Events"/>
public ReadOnlySpan<AutomationEvent> EventsAsSpan => new(Events, (int)Count); public readonly ReadOnlySpan<AutomationEvent> EventsAsSpan => new ReadOnlySpan<AutomationEvent>(Events, (int)Count);
} }

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// Camera2D, defines position/orientation in 2d space /// Camera2D, defines position/orientation in 2d space
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Camera2D public struct Camera2D
{ {
/// <summary> /// <summary>
/// Camera offset (displacement from target) /// Camera offset (displacement from target)

View File

@@ -28,7 +28,7 @@ public enum CameraProjection
/// Camera3D, defines position/orientation in 3d space /// Camera3D, defines position/orientation in 3d space
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Camera3D public struct Camera3D
{ {
/// <summary> /// <summary>
/// Camera position /// Camera position

View File

@@ -1,5 +1,5 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System;
namespace Raylib_cs; namespace Raylib_cs;
@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// Color type, RGBA (32bit) /// Color type, RGBA (32bit)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Color public struct Color
{ {
public byte R; public byte R;
public byte G; public byte G;
@@ -96,28 +96,133 @@ public partial struct Color
/// </summary> /// </summary>
public Color(float r, float g, float b, float a) public Color(float r, float g, float b, float a)
{ {
// X = (byte)Math.Clamp(MathF.Round(x * 255), 0f, 255f); this.R = (byte)(Math.Clamp(r, 0.0f, 1.0f) * 255);
this.R = (byte)((r < 0) ? 0 : ((r > 1) ? 255 : ((r * 255) + .5f))); this.G = (byte)(Math.Clamp(g, 0.0f, 1.0f) * 255);
this.G = (byte)((g < 0) ? 0 : ((g > 1) ? 255 : ((g * 255) + .5f))); this.B = (byte)(Math.Clamp(b, 0.0f, 1.0f) * 255);
this.B = (byte)((b < 0) ? 0 : ((b > 1) ? 255 : ((b * 255) + .5f))); this.A = (byte)(Math.Clamp(a, 0.0f, 1.0f) * 255);
this.A = (byte)((a < 0) ? 0 : ((a > 1) ? 255 : ((a * 255) + .5f)));
} }
/// <summary> /// <summary>
/// <inheritdoc cref="Color(byte, byte, byte)"/>. /// <inheritdoc cref="Color(byte, byte, byte)"/>.
/// Accepts <see cref="float"/>'s, upscales and clamps them to the range 0..255. /// Accepts <see cref="float"/>'s, upscales and clamps them to the range 0...255.
/// Then they are converted to <see cref="byte"/>'s by rounding. /// Then they are converted to <see cref="byte"/>'s by rounding.
/// </summary> /// </summary>
public Color(float r, float g, float b) public Color(float r, float g, float b)
{ {
// X = (byte)Math.Clamp(MathF.Round(x * 255), 0f, 255f); this.R = (byte)(Math.Clamp(r, 0.0f, 1.0f) * 255);
this.R = (byte)((r < 0) ? 0 : ((r > 1) ? 255 : ((r * 255) + .5f))); this.G = (byte)(Math.Clamp(g, 0.0f, 1.0f) * 255);
this.G = (byte)((g < 0) ? 0 : ((g > 1) ? 255 : ((g * 255) + .5f))); this.B = (byte)(Math.Clamp(b, 0.0f, 1.0f) * 255);
this.B = (byte)((b < 0) ? 0 : ((b > 1) ? 255 : ((b * 255) + .5f)));
this.A = 255; this.A = 255;
} }
public override string ToString() public readonly void GetHSV(out float h, out float s, out float v)
{
float rf = this.R / 255f;
float gf = this.G / 255f;
float bf = this.B / 255f;
float max = MathF.Max(rf, MathF.Max(gf, bf));
float min = MathF.Min(rf, MathF.Min(gf, bf));
float delta = max - min;
// Value
v = max;
// Saturation
s = (max == 0f) ? 0f : delta / max;
// Hue
if (delta == 0f)
{
h = 0f;
}
else if (max == rf)
{
h = 60f * (((gf - bf) / delta) % 6f);
}
else if (max == gf)
{
h = 60f * (((bf - rf) / delta) + 2f);
}
else // max == bf
{
h = 60f * (((rf - gf) / delta) + 4f);
}
// Keep h inside 0 and 360
if (h < 0f)
{
h += 360f;
}
}
public static Color FromHSV(float h, float s, float v)
{
float c = v * s;
float x = c * (1f - MathF.Abs((h / 60f) % 2f - 1f));
float m = v - c;
float rf, gf, bf;
if (h < 60f)
{
rf = c;
gf = x;
bf = 0;
}
else if (h < 120f)
{
rf = x;
gf = c;
bf = 0;
}
else if (h < 180f)
{
rf = 0;
gf = c;
bf = x;
}
else if (h < 240f)
{
rf = 0;
gf = x;
bf = c;
}
else if (h < 300f)
{
rf = x;
gf = 0;
bf = c;
}
else
{
rf = c;
gf = 0;
bf = x;
}
byte r = (byte)((rf + m) * 255f + 0.5f);
byte g = (byte)((gf + m) * 255f + 0.5f);
byte b = (byte)((bf + m) * 255f + 0.5f);
return new Color(r, g, b, byte.MaxValue);
}
public static Color Lerp(Color origin, Color target, float t)
{
byte r = LerpB(origin.R, target.R, t);
byte g = LerpB(origin.R, target.G, t);
byte b = LerpB(origin.R, target.B, t);
byte a = LerpB(origin.R, target.A, t);
return new Color(r, g, b, a);
}
// Lerp byte
private static byte LerpB(byte a, byte b, float t)
{
return (byte)(a + (b - a) * t);
}
public readonly override string ToString()
{ {
return $"{{R:{R} G:{G} B:{B} A:{A}}}"; return $"{{R:{R} G:{G} B:{B} A:{A}}}";
} }

View File

@@ -59,7 +59,7 @@ public partial struct GlyphInfo
/// Font, font texture and GlyphInfo array data /// Font, font texture and GlyphInfo array data
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Font public unsafe struct Font
{ {
/// <summary> /// <summary>
/// Base size (default chars height) /// Base size (default chars height)

View File

@@ -1,4 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Numerics;
namespace Raylib_cs; namespace Raylib_cs;
@@ -133,7 +134,7 @@ public enum PixelFormat
/// Image, pixel data stored in CPU memory (RAM) /// Image, pixel data stored in CPU memory (RAM)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Image public unsafe struct Image
{ {
/// <summary> /// <summary>
/// Image raw data /// Image raw data
@@ -159,4 +160,9 @@ public unsafe partial struct Image
/// Data format (PixelFormat type) /// Data format (PixelFormat type)
/// </summary> /// </summary>
public PixelFormat Format; public PixelFormat Format;
/// <summary>
/// Get width and height packed in a Vector2
/// </summary>
public readonly Vector2 Dimensions => new Vector2(Width, Height);
} }

View File

@@ -29,7 +29,7 @@ internal readonly struct Native
} }
[StructLayout(LayoutKind.Sequential, Pack = 4)] [StructLayout(LayoutKind.Sequential, Pack = 4)]
struct VaListLinuxX64 internal struct VaListLinuxX64
{ {
uint _gpOffset; uint _gpOffset;
uint _fpOffset; uint _fpOffset;
@@ -42,10 +42,10 @@ struct VaListLinuxX64
/// </summary> /// </summary>
public static unsafe class Logging 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) 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); Console.WriteLine(message);
} }
@@ -62,13 +62,13 @@ public static unsafe class Logging
return LinuxX64LogCallback(format, args); 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) if (byteLength <= 1)
{ {
return string.Empty; return string.Empty;
} }
var buffer = Marshal.AllocHGlobal(byteLength); IntPtr buffer = Marshal.AllocHGlobal(byteLength);
VsPrintf(buffer, format, args); VsPrintf(buffer, format, args);
string result = Marshal.PtrToStringUTF8(buffer); string result = Marshal.PtrToStringUTF8(buffer);
@@ -77,12 +77,12 @@ public static unsafe class Logging
return result; return result;
} }
static string AppleLogCallback(IntPtr format, IntPtr args) private static string AppleLogCallback(IntPtr format, IntPtr args)
{ {
IntPtr buffer = IntPtr.Zero; IntPtr buffer = IntPtr.Zero;
try try
{ {
var count = Native.VasPrintfApple(ref buffer, format, args); int count = Native.VasPrintfApple(ref buffer, format, args);
if (count == -1) if (count == -1)
{ {
return string.Empty; return string.Empty;
@@ -95,10 +95,10 @@ public static unsafe class Logging
} }
} }
static string LinuxX64LogCallback(IntPtr format, IntPtr args) private 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. // The args pointer cannot be reused between two calls. We need to make a copy of the underlying structure.
var listStructure = Marshal.PtrToStructure<VaListLinuxX64>(args); VaListLinuxX64 listStructure = Marshal.PtrToStructure<VaListLinuxX64>(args);
IntPtr listPointer = IntPtr.Zero; IntPtr listPointer = IntPtr.Zero;
int byteLength = 0; int byteLength = 0;
string result = ""; string result = "";
@@ -125,9 +125,9 @@ public static unsafe class Logging
} }
// https://github.com/dotnet/runtime/issues/51052 // https://github.com/dotnet/runtime/issues/51052
static int VsnPrintf(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args) private static int VsnPrintf(IntPtr buffer, UIntPtr size, IntPtr format, IntPtr args)
{ {
var os = Environment.OSVersion; OperatingSystem os = Environment.OSVersion;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
return Native.VsnPrintfWindows(buffer, size, format, args); return Native.VsnPrintfWindows(buffer, size, format, args);
@@ -144,7 +144,7 @@ public static unsafe class Logging
} }
// https://github.com/dotnet/runtime/issues/51052 // https://github.com/dotnet/runtime/issues/51052
static int VsPrintf(IntPtr buffer, IntPtr format, IntPtr args) private static int VsPrintf(IntPtr buffer, IntPtr format, IntPtr args)
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {

View File

@@ -48,7 +48,7 @@ public enum MaterialMapIndex
/// Material texture map /// Material texture map
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct MaterialMap public struct MaterialMap
{ {
/// <summary> /// <summary>
/// Material map texture /// Material map texture
@@ -70,7 +70,7 @@ public partial struct MaterialMap
/// Material type (generic) /// Material type (generic)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Material public unsafe struct Material
{ {
/// <summary> /// <summary>
/// Material shader /// Material shader

View File

@@ -9,7 +9,7 @@ namespace Raylib_cs;
/// NOTE: Data stored in CPU memory (and GPU) /// NOTE: Data stored in CPU memory (and GPU)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Mesh public unsafe struct Mesh
{ {
/// <summary> /// <summary>
/// Creates a mesh ready for default vertex data allocation /// Creates a mesh ready for default vertex data allocation
@@ -136,7 +136,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> TexCoordsAs<T>() where T : unmanaged public readonly Span<T> TexCoordsAs<T>() where T : unmanaged
{ {
return new(TexCoords, 2 * VertexCount * sizeof(float) / sizeof(T)); return new Span<T>(TexCoords, 2 * VertexCount * sizeof(float) / sizeof(T));
} }
/// <summary> /// <summary>
@@ -144,7 +144,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> TexCoords2As<T>() where T : unmanaged public readonly Span<T> TexCoords2As<T>() where T : unmanaged
{ {
return new(TexCoords2, 2 * VertexCount * sizeof(float) / sizeof(T)); return new Span<T>(TexCoords2, 2 * VertexCount * sizeof(float) / sizeof(T));
} }
/// <summary> /// <summary>
@@ -152,7 +152,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> NormalsAs<T>() where T : unmanaged public readonly Span<T> NormalsAs<T>() where T : unmanaged
{ {
return new(Normals, 3 * VertexCount * sizeof(float) / sizeof(T)); return new Span<T>(Normals, 3 * VertexCount * sizeof(float) / sizeof(T));
} }
/// <summary> /// <summary>
@@ -160,7 +160,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> TangentsAs<T>() where T : unmanaged public readonly Span<T> TangentsAs<T>() where T : unmanaged
{ {
return new(Tangents, 4 * VertexCount * sizeof(float) / sizeof(T)); return new Span<T>(Tangents, 4 * VertexCount * sizeof(float) / sizeof(T));
} }
/// <summary> /// <summary>
@@ -168,7 +168,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> ColorsAs<T>() where T : unmanaged public readonly Span<T> ColorsAs<T>() where T : unmanaged
{ {
return new(Colors, 4 * VertexCount * sizeof(byte) / sizeof(T)); return new Span<T>(Colors, 4 * VertexCount * sizeof(byte) / sizeof(T));
} }
/// <summary> /// <summary>
@@ -176,7 +176,7 @@ public unsafe partial struct Mesh
/// </summary> /// </summary>
public readonly Span<T> IndicesAs<T>() where T : unmanaged public readonly Span<T> IndicesAs<T>() where T : unmanaged
{ {
return new(Indices, 3 * TriangleCount * sizeof(ushort) / sizeof(T)); return new Span<T>(Indices, 3 * TriangleCount * sizeof(ushort) / sizeof(T));
} }
#endregion #endregion

View File

@@ -8,7 +8,7 @@ namespace Raylib_cs;
/// Bone information /// Bone information
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct BoneInfo public unsafe struct BoneInfo
{ {
/// <summary> /// <summary>
/// Bone name (char[32]) /// Bone name (char[32])
@@ -25,7 +25,7 @@ public unsafe partial struct BoneInfo
/// Model type /// Model type
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Model public unsafe struct Model
{ {
/// <summary> /// <summary>
/// Local transform matrix /// Local transform matrix
@@ -79,7 +79,7 @@ public unsafe partial struct Model
/// Model animation /// Model animation
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct ModelAnimation public unsafe struct ModelAnimation
{ {
/// <summary> /// <summary>
/// Number of bones /// Number of bones
@@ -97,7 +97,7 @@ public unsafe partial struct ModelAnimation
public readonly BoneInfo* Bones; public readonly BoneInfo* Bones;
/// <inheritdoc cref="Bones"/> /// <inheritdoc cref="Bones"/>
public ReadOnlySpan<BoneInfo> BoneInfo => new(Bones, BoneCount); public readonly ReadOnlySpan<BoneInfo> BoneInfo => new ReadOnlySpan<BoneInfo>(Bones, BoneCount);
/// <summary> /// <summary>
/// Poses array by frame (Transform **) /// Poses array by frame (Transform **)
@@ -110,9 +110,9 @@ public unsafe partial struct ModelAnimation
public fixed sbyte Name[32]; public fixed sbyte Name[32];
/// <inheritdoc cref="FramePoses"/> /// <inheritdoc cref="FramePoses"/>
public FramePosesCollection FramePosesColl => new(FramePoses, FrameCount, BoneCount); public readonly FramePosesCollection FramePosesColl => new FramePosesCollection(FramePoses, FrameCount, BoneCount);
public struct FramePosesCollection public readonly struct FramePosesCollection
{ {
readonly Transform** _framePoses; readonly Transform** _framePoses;
@@ -120,9 +120,9 @@ public unsafe partial struct ModelAnimation
readonly int _boneCount; readonly int _boneCount;
public FramePoses this[int index] => new(_framePoses[index], _boneCount); public readonly FramePoses this[int index] => new FramePoses(_framePoses[index], _boneCount);
public Transform this[int index1, int index2] => new FramePoses(_framePoses[index1], _boneCount)[index2]; public readonly Transform this[int index1, int index2] => new FramePoses(_framePoses[index1], _boneCount)[index2];
internal FramePosesCollection(Transform** framePoses, int frameCount, int boneCount) internal FramePosesCollection(Transform** framePoses, int frameCount, int boneCount)
{ {
@@ -133,13 +133,13 @@ public unsafe partial struct ModelAnimation
} }
} }
public unsafe struct FramePoses public readonly unsafe struct FramePoses
{ {
readonly Transform* _poses; readonly Transform* _poses;
readonly int _count; readonly int _count;
public ref Transform this[int index] => ref _poses[index]; public readonly ref Transform this[int index] => ref _poses[index];
internal FramePoses(Transform* poses, int count) internal FramePoses(Transform* poses, int count)
{ {

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// NOTE: Anything longer than ~10 seconds should be streamed /// NOTE: Anything longer than ~10 seconds should be streamed
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Music public unsafe struct Music
{ {
/// <summary> /// <summary>
/// Audio stream /// Audio stream

View File

@@ -27,7 +27,7 @@ public enum NPatchLayout
/// N-Patch layout info /// N-Patch layout info
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct NPatchInfo public struct NPatchInfo
{ {
/// <summary> /// <summary>
/// Texture source rectangle /// Texture source rectangle

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// Ray, ray for raycasting /// Ray, ray for raycasting
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Ray public struct Ray
{ {
/// <summary> /// <summary>
/// Ray position (origin) /// Ray position (origin)
@@ -30,7 +30,7 @@ public partial struct Ray
/// Raycast hit information /// Raycast hit information
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct RayCollision public struct RayCollision
{ {
/// <summary> /// <summary>
/// Did the ray hit something? /// Did the ray hit something?

View File

@@ -1,6 +1,6 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Numerics;
using System;
namespace Raylib_cs; namespace Raylib_cs;
@@ -9,14 +9,14 @@ public static unsafe partial class Raylib
/// <summary>Initialize window and OpenGL context</summary> /// <summary>Initialize window and OpenGL context</summary>
public static void InitWindow(int width, int height, string title) public static void InitWindow(int width, int height, string title)
{ {
using var str1 = title.ToUtf8Buffer(); using Utf8Buffer str1 = title.ToUtf8Buffer();
InitWindow(width, height, str1.AsPointer()); InitWindow(width, height, str1.AsPointer());
} }
/// <summary>Set title for window (only PLATFORM_DESKTOP)</summary> /// <summary>Set title for window (only PLATFORM_DESKTOP)</summary>
public static void SetWindowTitle(string title) public static void SetWindowTitle(string title)
{ {
using var str1 = title.ToUtf8Buffer(); using Utf8Buffer str1 = title.ToUtf8Buffer();
SetWindowTitle(str1.AsPointer()); SetWindowTitle(str1.AsPointer());
} }
@@ -35,94 +35,94 @@ public static unsafe partial class Raylib
/// <summary>Set clipboard text content</summary> /// <summary>Set clipboard text content</summary>
public static void SetClipboardText(string text) public static void SetClipboardText(string text)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
SetClipboardText(str1.AsPointer()); SetClipboardText(str1.AsPointer());
} }
/// <summary>Open URL with default system browser (if available)</summary> /// <summary>Open URL with default system browser (if available)</summary>
public static void OpenURL(string url) public static void OpenURL(string url)
{ {
using var str1 = url.ToUtf8Buffer(); using Utf8Buffer str1 = url.ToUtf8Buffer();
OpenURL(str1.AsPointer()); OpenURL(str1.AsPointer());
} }
/// <summary>Set internal gamepad mappings (SDL_GameControllerDB)</summary> /// <summary>Set internal gamepad mappings (SDL_GameControllerDB)</summary>
public static int SetGamepadMappings(string mappings) public static int SetGamepadMappings(string mappings)
{ {
using var str1 = mappings.ToUtf8Buffer(); using Utf8Buffer str1 = mappings.ToUtf8Buffer();
return SetGamepadMappings(str1.AsPointer()); return SetGamepadMappings(str1.AsPointer());
} }
/// <summary>Load shader from files and bind default locations</summary> /// <summary>Load shader from files and bind default locations</summary>
public static Shader LoadShader(string vsFileName, string fsFileName) public static Shader LoadShader(string vsFileName, string fsFileName)
{ {
using var str1 = vsFileName.ToAnsiBuffer(); using AnsiBuffer str1 = vsFileName.ToAnsiBuffer();
using var str2 = fsFileName.ToAnsiBuffer(); using AnsiBuffer str2 = fsFileName.ToAnsiBuffer();
return LoadShader(str1.AsPointer(), str2.AsPointer()); return LoadShader(str1.AsPointer(), str2.AsPointer());
} }
/// <summary>Load shader from code string and bind default locations</summary> /// <summary>Load shader from code string and bind default locations</summary>
public static Shader LoadShaderFromMemory(string vsCode, string fsCode) public static Shader LoadShaderFromMemory(string vsCode, string fsCode)
{ {
using var str1 = vsCode.ToUtf8Buffer(); using Utf8Buffer str1 = vsCode.ToUtf8Buffer();
using var str2 = fsCode.ToUtf8Buffer(); using Utf8Buffer str2 = fsCode.ToUtf8Buffer();
return LoadShaderFromMemory(str1.AsPointer(), str2.AsPointer()); return LoadShaderFromMemory(str1.AsPointer(), str2.AsPointer());
} }
/// <summary>Get shader uniform location</summary> /// <summary>Get shader uniform location</summary>
public static int GetShaderLocation(Shader shader, string uniformName) public static int GetShaderLocation(Shader shader, string uniformName)
{ {
using var str1 = uniformName.ToUtf8Buffer(); using Utf8Buffer str1 = uniformName.ToUtf8Buffer();
return GetShaderLocation(shader, str1.AsPointer()); return GetShaderLocation(shader, str1.AsPointer());
} }
/// <summary>Get shader attribute location</summary> /// <summary>Get shader attribute location</summary>
public static int GetShaderLocationAttrib(Shader shader, string attribName) public static int GetShaderLocationAttrib(Shader shader, string attribName)
{ {
using var str1 = attribName.ToUtf8Buffer(); using Utf8Buffer str1 = attribName.ToUtf8Buffer();
return GetShaderLocationAttrib(shader, str1.AsPointer()); return GetShaderLocationAttrib(shader, str1.AsPointer());
} }
/// <summary>Takes a screenshot of current screen (saved a .png)</summary> /// <summary>Takes a screenshot of current screen (saved a .png)</summary>
public static void TakeScreenshot(string fileName) public static void TakeScreenshot(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
TakeScreenshot(str1.AsPointer()); TakeScreenshot(str1.AsPointer());
} }
/// <summary>Check file extension</summary> /// <summary>Check file extension</summary>
public static CBool IsFileExtension(string fileName, string ext) public static CBool IsFileExtension(string fileName, string ext)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
using var str2 = ext.ToAnsiBuffer(); using AnsiBuffer str2 = ext.ToAnsiBuffer();
return IsFileExtension(str1.AsPointer(), str2.AsPointer()); return IsFileExtension(str1.AsPointer(), str2.AsPointer());
} }
/// <summary>Get file modification time (last write time)</summary> /// <summary>Get file modification time (last write time)</summary>
public static long GetFileModTime(string fileName) public static long GetFileModTime(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return GetFileModTime(str1.AsPointer()); return GetFileModTime(str1.AsPointer());
} }
/// <summary>Load image from file into CPU memory (RAM)</summary> /// <summary>Load image from file into CPU memory (RAM)</summary>
public static Image LoadImage(string fileName) public static Image LoadImage(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadImage(str1.AsPointer()); return LoadImage(str1.AsPointer());
} }
/// <summary>Load image from RAW file data</summary> /// <summary>Load image from RAW file data</summary>
public static Image LoadImageRaw(string fileName, int width, int height, PixelFormat format, int headerSize) public static Image LoadImageRaw(string fileName, int width, int height, PixelFormat format, int headerSize)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadImageRaw(str1.AsPointer(), width, height, format, headerSize); return LoadImageRaw(str1.AsPointer(), width, height, format, headerSize);
} }
/// <summary>Load image sequence from file (frames appended to image.data)</summary> /// <summary>Load image sequence from file (frames appended to image.data)</summary>
public static Image LoadImageAnim(string fileName, out int frames) public static Image LoadImageAnim(string fileName, out int frames)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
fixed (int* p = &frames) fixed (int* p = &frames)
{ {
return LoadImageAnim(str1.AsPointer(), p); return LoadImageAnim(str1.AsPointer(), p);
@@ -134,7 +134,7 @@ public static unsafe partial class Raylib
/// </summary> /// </summary>
public static Image LoadImageFromMemory(string fileType, byte[] fileData) public static Image LoadImageFromMemory(string fileType, byte[] fileData)
{ {
using var fileTypeNative = fileType.ToAnsiBuffer(); using AnsiBuffer fileTypeNative = fileType.ToAnsiBuffer();
fixed (byte* fileDataNative = fileData) fixed (byte* fileDataNative = fileData)
{ {
Image image = LoadImageFromMemory(fileTypeNative.AsPointer(), fileDataNative, fileData.Length); Image image = LoadImageFromMemory(fileTypeNative.AsPointer(), fileDataNative, fileData.Length);
@@ -145,21 +145,21 @@ public static unsafe partial class Raylib
/// <summary>Export image data to file</summary> /// <summary>Export image data to file</summary>
public static CBool ExportImage(Image image, string fileName) public static CBool ExportImage(Image image, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportImage(image, str1.AsPointer()); return ExportImage(image, str1.AsPointer());
} }
/// <summary>Export image as code file defining an array of bytes</summary> /// <summary>Export image as code file defining an array of bytes</summary>
public static CBool ExportImageAsCode(Image image, string fileName) public static CBool ExportImageAsCode(Image image, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportImageAsCode(image, str1.AsPointer()); return ExportImageAsCode(image, str1.AsPointer());
} }
/// <summary>Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR)</summary> /// <summary>Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR)</summary>
public static void TraceLog(TraceLogLevel logLevel, string text) public static void TraceLog(TraceLogLevel logLevel, string text)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
TraceLog(logLevel, str1.AsPointer()); TraceLog(logLevel, str1.AsPointer());
} }
@@ -228,25 +228,71 @@ public static unsafe partial class Raylib
return (T*)MemAlloc(count * (uint)sizeof(T)); return (T*)MemAlloc(count * (uint)sizeof(T));
} }
/// <summary>Save data to file from an unmanaged type</summary>
/// <returns>True if the operation was successfully</returns>
public static CBool SaveFileData<T>(T data, string fileName) where T : unmanaged
{
using AnsiBuffer ansiBuffer = fileName.ToAnsiBuffer();
return SaveFileData(ansiBuffer.AsPointer(), &data, sizeof(T));
}
/// <summary>Save data to file from an unmanaged type</summary>
/// <returns>True if the operation was successfully</returns>
public static CBool SaveFileData<T>(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);
}
}
/// <summary>Load file data as byte array (read)</summary> /// <summary>Load file data as byte array (read)</summary>
public static byte* LoadFileData(string fileName, ref int bytesRead) public static byte* LoadFileData(string fileName, ref int bytesRead)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
fixed (int* p = &bytesRead) fixed (int* p = &bytesRead)
{ {
return LoadFileData(str1.AsPointer(), p); return LoadFileData(str1.AsPointer(), p);
} }
} }
public static byte[] LoadFileData(string fileName)
{
int length = 0;
byte* data = LoadFileData(fileName, ref length);
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)data, arr, 0, length);
UnloadFileData(data);
return arr;
}
/// <summary>
/// Load file data as an array of unmanaged types
/// </summary>
public static T[] LoadFileData<T>(string fileName) where T : unmanaged
{
int length = 0;
byte* data = LoadFileData(fileName, ref length);
Span<T> values = new Span<T>(data, length / sizeof(T));
T[] arr = values.ToArray();
UnloadFileData(data);
return arr;
}
/// <summary>Get dropped files names (memory should be freed)</summary> /// <summary>Get dropped files names (memory should be freed)</summary>
public static string[] GetDroppedFiles() public static string[] GetDroppedFiles()
{ {
var filePathList = LoadDroppedFiles(); FilePathList filePathList = LoadDroppedFiles();
var files = new string[filePathList.Count]; string[] files = new string[filePathList.Count];
for (var 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); UnloadDroppedFiles(filePathList);
@@ -426,21 +472,21 @@ public static unsafe partial class Raylib
/// <summary>Generate image: grayscale image from text data</summary> /// <summary>Generate image: grayscale image from text data</summary>
public static Image GenImageText(int width, int height, string text) public static Image GenImageText(int width, int height, string text)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return GenImageText(width, height, str1.AsPointer()); return GenImageText(width, height, str1.AsPointer());
} }
/// <summary>Create an image from text (default font)</summary> /// <summary>Create an image from text (default font)</summary>
public static Image ImageText(string text, int fontSize, Color color) public static Image ImageText(string text, int fontSize, Color color)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return ImageText(str1.AsPointer(), fontSize, color); return ImageText(str1.AsPointer(), fontSize, color);
} }
/// <summary>Create an image from text (custom sprite font)</summary> /// <summary>Create an image from text (custom sprite font)</summary>
public static Image ImageTextEx(Font font, string text, float fontSize, float spacing, Color tint) public static Image ImageTextEx(Font font, string text, float fontSize, float spacing, Color tint)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return ImageTextEx(font, str1.AsPointer(), fontSize, spacing, tint); return ImageTextEx(font, str1.AsPointer(), fontSize, spacing, tint);
} }
@@ -749,6 +795,22 @@ public static unsafe partial class Raylib
} }
} }
public static void ImageDrawCircleLines(ref Image dst, int centerX, int centerY, int radius, Color color)
{
fixed (Image* p = &dst)
{
ImageDrawCircleLines(p, centerX, centerY, radius, color);
}
}
public static void ImageDrawCircleLinesV(ref Image dst, Vector2 center, int radius, Color color)
{
fixed (Image* p = &dst)
{
ImageDrawCircleLinesV(p, center, radius, color);
}
}
/// <summary>Draw circle within an image (Vector version)</summary> /// <summary>Draw circle within an image (Vector version)</summary>
public static void ImageDrawCircleV(ref Image dst, Vector2 center, int radius, Color color) public static void ImageDrawCircleV(ref Image dst, Vector2 center, int radius, Color color)
{ {
@@ -857,7 +919,7 @@ public static unsafe partial class Raylib
/// <summary>Draw text (using default font) within an image (destination)</summary> /// <summary>Draw text (using default font) within an image (destination)</summary>
public static void ImageDrawText(ref Image dst, string text, int x, int y, int fontSize, Color color) public static void ImageDrawText(ref Image dst, string text, int x, int y, int fontSize, Color color)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
fixed (Image* p = &dst) fixed (Image* p = &dst)
{ {
ImageDrawText(p, str1.AsPointer(), x, y, fontSize, color); ImageDrawText(p, str1.AsPointer(), x, y, fontSize, color);
@@ -875,7 +937,7 @@ public static unsafe partial class Raylib
Color color Color color
) )
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
fixed (Image* p = &dst) fixed (Image* p = &dst)
{ {
ImageDrawTextEx(p, font, str1.AsPointer(), position, fontSize, spacing, color); ImageDrawTextEx(p, font, str1.AsPointer(), position, fontSize, spacing, color);
@@ -885,7 +947,7 @@ public static unsafe partial class Raylib
/// <summary>Load texture from file into GPU memory (VRAM)</summary> /// <summary>Load texture from file into GPU memory (VRAM)</summary>
public static Texture2D LoadTexture(string fileName) public static Texture2D LoadTexture(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadTexture(str1.AsPointer()); return LoadTexture(str1.AsPointer());
} }
@@ -931,7 +993,7 @@ public static unsafe partial class Raylib
/// <summary>Load font from file into GPU memory (VRAM)</summary> /// <summary>Load font from file into GPU memory (VRAM)</summary>
public static Font LoadFont(string fileName) public static Font LoadFont(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadFont(str1.AsPointer()); return LoadFont(str1.AsPointer());
} }
@@ -941,7 +1003,7 @@ public static unsafe partial class Raylib
/// </summary> /// </summary>
public static Font LoadFontEx(string fileName, int fontSize, int[] codepoints, int codepointCount) public static Font LoadFontEx(string fileName, int fontSize, int[] codepoints, int codepointCount)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
fixed (int* p = codepoints) fixed (int* p = codepoints)
{ {
return LoadFontEx(str1.AsPointer(), fontSize, p, codepointCount); return LoadFontEx(str1.AsPointer(), fontSize, p, codepointCount);
@@ -959,7 +1021,7 @@ public static unsafe partial class Raylib
int codepointCount int codepointCount
) )
{ {
using var fileTypeNative = fileType.ToAnsiBuffer(); using AnsiBuffer fileTypeNative = fileType.ToAnsiBuffer();
fixed (byte* fileDataNative = fileData) fixed (byte* fileDataNative = fileData)
{ {
fixed (int* fontCharsNative = codepoints) fixed (int* fontCharsNative = codepoints)
@@ -972,7 +1034,6 @@ public static unsafe partial class Raylib
fontCharsNative, fontCharsNative,
codepointCount codepointCount
); );
return font; return font;
} }
} }
@@ -1017,7 +1078,7 @@ public static unsafe partial class Raylib
/// <summary>Load model animations from file</summary> /// <summary>Load model animations from file</summary>
public static ModelAnimation* LoadModelAnimations(string fileName, ref int animCount) public static ModelAnimation* LoadModelAnimations(string fileName, ref int animCount)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
fixed (int* p = &animCount) fixed (int* p = &animCount)
{ {
return LoadModelAnimations(str1.AsPointer(), p); return LoadModelAnimations(str1.AsPointer(), p);
@@ -1126,21 +1187,14 @@ public static unsafe partial class Raylib
/// <summary>Draw text (using default font)</summary> /// <summary>Draw text (using default font)</summary>
public static void DrawText(string text, int posX, int posY, int fontSize, Color color) public static void DrawText(string text, int posX, int posY, int fontSize, Color color)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
DrawText(str1.AsPointer(), posX, posY, fontSize, color); DrawText(str1.AsPointer(), posX, posY, fontSize, color);
} }
/// <summary>Draw text using font and additional parameters</summary> /// <summary>Draw text using font and additional parameters</summary>
public static void DrawTextEx( public static void DrawTextEx(Font font, string text, Vector2 position, float fontSize, float spacing, Color tint)
Font font,
string text,
Vector2 position,
float fontSize,
float spacing,
Color tint
)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
DrawTextEx(font, str1.AsPointer(), position, fontSize, spacing, tint); DrawTextEx(font, str1.AsPointer(), position, fontSize, spacing, tint);
} }
@@ -1156,32 +1210,32 @@ public static unsafe partial class Raylib
Color tint Color tint
) )
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
DrawTextPro(font, str1.AsPointer(), position, origin, rotation, fontSize, spacing, tint); DrawTextPro(font, str1.AsPointer(), position, origin, rotation, fontSize, spacing, tint);
} }
/// <summary>Measure string width for default font</summary> /// <summary>Measure string width for default font</summary>
public static int MeasureText(string text, int fontSize) public static int MeasureText(string text, int fontSize)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return MeasureText(str1.AsPointer(), fontSize); return MeasureText(str1.AsPointer(), fontSize);
} }
/// <summary>Measure string size for Font</summary> /// <summary>Measure string size for Font</summary>
public static Vector2 MeasureTextEx(Font font, string text, float fontSize, float spacing) public static Vector2 MeasureTextEx(Font font, string text, float fontSize, float spacing)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return MeasureTextEx(font, str1.AsPointer(), fontSize, spacing); return MeasureTextEx(font, str1.AsPointer(), fontSize, spacing);
} }
/// <summary>Get all codepoints in a string, codepoints count returned by parameters</summary> /// <summary>Get all codepoints in a string, codepoints count returned by parameters</summary>
public static int[] LoadCodepoints(string text, ref int count) public static int[] LoadCodepoints(string text, ref int count)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
fixed (int* c = &count) fixed (int* c = &count)
{ {
var pointsPtr = LoadCodepoints(str1.AsPointer(), c); int* pointsPtr = LoadCodepoints(str1.AsPointer(), c);
var codepoints = new ReadOnlySpan<int>(pointsPtr, count).ToArray(); int[] codepoints = new ReadOnlySpan<int>(pointsPtr, count).ToArray();
UnloadCodepoints(pointsPtr); UnloadCodepoints(pointsPtr);
return codepoints; return codepoints;
} }
@@ -1190,14 +1244,14 @@ public static unsafe partial class Raylib
/// <summary>Get total number of codepoints in a UTF8 encoded string</summary> /// <summary>Get total number of codepoints in a UTF8 encoded string</summary>
public static int GetCodepointCount(string text) public static int GetCodepointCount(string text)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
return GetCodepointCount(str1.AsPointer()); return GetCodepointCount(str1.AsPointer());
} }
/// <summary>Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure</summary> /// <summary>Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure</summary>
public static int GetCodepoint(string text, ref int codepointSize) public static int GetCodepoint(string text, ref int codepointSize)
{ {
using var str1 = text.ToUtf8Buffer(); using Utf8Buffer str1 = text.ToUtf8Buffer();
fixed (int* p = &codepointSize) fixed (int* p = &codepointSize)
{ {
return GetCodepoint(str1.AsPointer(), p); return GetCodepoint(str1.AsPointer(), p);
@@ -1209,7 +1263,7 @@ public static unsafe partial class Raylib
{ {
fixed (int* l1 = &utf8Size) fixed (int* l1 = &utf8Size)
{ {
var ptr = CodepointToUTF8(codepoint, l1); sbyte* ptr = CodepointToUTF8(codepoint, l1);
return Utf8StringUtils.GetUTF8String(ptr); return Utf8StringUtils.GetUTF8String(ptr);
} }
} }
@@ -1219,8 +1273,8 @@ public static unsafe partial class Raylib
{ {
fixed (int* c1 = codepoints) fixed (int* c1 = codepoints)
{ {
var ptr = LoadUTF8(c1, length); sbyte* ptr = LoadUTF8(c1, length);
var text = Utf8StringUtils.GetUTF8String(ptr); string text = Utf8StringUtils.GetUTF8String(ptr);
MemFree(ptr); MemFree(ptr);
return text; return text;
} }
@@ -1229,21 +1283,21 @@ public static unsafe partial class Raylib
/// <summary>Draw a model (with texture if set)</summary> /// <summary>Draw a model (with texture if set)</summary>
public static Model LoadModel(string fileName) public static Model LoadModel(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadModel(str1.AsPointer()); return LoadModel(str1.AsPointer());
} }
/// <summary>Export mesh data to file, returns true on success</summary> /// <summary>Export mesh data to file, returns true on success</summary>
public static CBool ExportMesh(Mesh mesh, string fileName) public static CBool ExportMesh(Mesh mesh, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportMesh(mesh, str1.AsPointer()); return ExportMesh(mesh, str1.AsPointer());
} }
/// <summary>Export mesh as code file (.h) defining multiple arrays of vertex attributes</summary> /// <summary>Export mesh as code file (.h) defining multiple arrays of vertex attributes</summary>
public static CBool ExportMeshAsCode(Mesh mesh, string fileName) public static CBool ExportMeshAsCode(Mesh mesh, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportMeshAsCode(mesh, str1.AsPointer()); return ExportMeshAsCode(mesh, str1.AsPointer());
} }
@@ -1268,19 +1322,16 @@ public static unsafe partial class Raylib
/// <summary>Load wave data from file</summary> /// <summary>Load wave data from file</summary>
public static Wave LoadWave(string fileName) public static Wave LoadWave(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadWave(str1.AsPointer()); return LoadWave(str1.AsPointer());
} }
/// <summary> /// <summary>
/// Load wave from managed memory, fileType refers to extension: i.e. ".wav" /// Load wave from managed memory, fileType refers to extension: i.e. ".wav"
/// </summary> /// </summary>
public static Wave LoadWaveFromMemory( public static Wave LoadWaveFromMemory(string fileType, byte[] fileData)
string fileType,
byte[] fileData
)
{ {
using var fileTypeNative = fileType.ToAnsiBuffer(); using AnsiBuffer fileTypeNative = fileType.ToAnsiBuffer();
fixed (byte* fileDataNative = fileData) fixed (byte* fileDataNative = fileData)
{ {
@@ -1297,40 +1348,37 @@ public static unsafe partial class Raylib
/// <summary>Load sound from file</summary> /// <summary>Load sound from file</summary>
public static Sound LoadSound(string fileName) public static Sound LoadSound(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadSound(str1.AsPointer()); return LoadSound(str1.AsPointer());
} }
/// <summary>Export wave data to file</summary> /// <summary>Export wave data to file</summary>
public static CBool ExportWave(Wave wave, string fileName) public static CBool ExportWave(Wave wave, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportWave(wave, str1.AsPointer()); return ExportWave(wave, str1.AsPointer());
} }
/// <summary>Export wave sample data to code (.h)</summary> /// <summary>Export wave sample data to code (.h)</summary>
public static CBool ExportWaveAsCode(Wave wave, string fileName) public static CBool ExportWaveAsCode(Wave wave, string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return ExportWaveAsCode(wave, str1.AsPointer()); return ExportWaveAsCode(wave, str1.AsPointer());
} }
/// <summary>Load music stream from file</summary> /// <summary>Load music stream from file</summary>
public static Music LoadMusicStream(string fileName) public static Music LoadMusicStream(string fileName)
{ {
using var str1 = fileName.ToAnsiBuffer(); using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return LoadMusicStream(str1.AsPointer()); return LoadMusicStream(str1.AsPointer());
} }
/// <summary> /// <summary>
/// Load music stream from managed memory, fileType refers to extension: i.e. ".wav" /// Load music stream from managed memory, fileType refers to extension: i.e. ".wav"
/// </summary> /// </summary>
public static Music LoadMusicStreamFromMemory( public static Music LoadMusicStreamFromMemory(string fileType, byte[] fileData)
string fileType,
byte[] fileData
)
{ {
using var fileTypeNative = fileType.ToAnsiBuffer(); using AnsiBuffer fileTypeNative = fileType.ToAnsiBuffer();
fixed (byte* fileDataNative = fileData) fixed (byte* fileDataNative = fileData)
{ {
@@ -1408,14 +1456,14 @@ public static unsafe partial class Raylib
/// <summary>Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS</summary> /// <summary>Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS</summary>
public static AutomationEventList LoadAutomationEventList(string fileName) public static AutomationEventList LoadAutomationEventList(string fileName)
{ {
using var str1 = fileName.ToUtf8Buffer(); using Utf8Buffer str1 = fileName.ToUtf8Buffer();
return LoadAutomationEventList(str1.AsPointer()); return LoadAutomationEventList(str1.AsPointer());
} }
/// <summary>Export automation events list as text file</summary> /// <summary>Export automation events list as text file</summary>
public static CBool ExportAutomationEventList(AutomationEventList list, string fileName) public static CBool ExportAutomationEventList(AutomationEventList list, string fileName)
{ {
using var str1 = fileName.ToUtf8Buffer(); using Utf8Buffer str1 = fileName.ToUtf8Buffer();
return ExportAutomationEventList(list, str1.AsPointer()); return ExportAutomationEventList(list, str1.AsPointer());
} }
@@ -1427,4 +1475,98 @@ public static unsafe partial class Raylib
SetAutomationEventList(p); SetAutomationEventList(p);
} }
} }
public static int MakeDirectory(string path)
{
using AnsiBuffer pathBuffer = path.ToAnsiBuffer();
return MakeDirectory(pathBuffer.AsPointer());
}
public static string GetApplicationDirectoryString()
{
return new string(GetApplicationDirectory());
}
public static string GetWorkingDirectoryString()
{
return new string(GetWorkingDirectory());
}
/// <summary>
/// Load a sequence of random numbers, store them and return them but not before unloading them.
/// </summary>
/// <param name="count">Amount of random numbers to load</param>
/// <param name="min">Minimum random value</param>
/// <param name="max">Maximum random value</param>
/// <returns>An array filled with the random numbers</returns>
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;
}
/// <summary>
/// Load a sequence of random numbers, store them and return them but not before unloading them.
/// </summary>
/// <param name="count">Amount of random numbers to load</param>
/// <param name="min">Minimum random value</param>
/// <param name="max">Maximum random value</param>
/// <returns>An array filled with the random numbers</returns>
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;
}
/// <summary>
/// Create a file in the specified path to save the specified text
/// </summary>
public static void SaveFileText(string fileName, string text)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
using AnsiBuffer textBuffer = text.ToAnsiBuffer();
SaveFileText(fileBuffer.AsPointer(), textBuffer.AsPointer());
}
/// <summary>
/// Loads text from a file, reads it, saves it, unloads the file, and returns the loaded text.
/// </summary>
/// <returns>The text content of the file on the given path</returns>
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;
}
public static Vector2 GetScreenCenter()
{
Vector2 center = new Vector2();
center.X = GetScreenWidth() / 2.0f;
center.Y = GetScreenHeight() / 2.0f;
return center;
}
} }

View File

@@ -0,0 +1,98 @@
using System;
namespace Raylib_cs;
public static partial class Raymath
{
public static float Clamp01(float value) => Clamp(value, 0.0f, 1.0f);
/// <summary>
/// Loops the value, so that it is never larger than length and never smaller than 0
/// </summary>
public static float Repeat(float value, float length)
{
return Clamp(value - MathF.Floor(value / length) * length, 0f, length);
}
/// <summary>
/// Same as Lerp but makes sure the values interpolate correctly when they wrap around
/// 360 degrees.
/// </summary>
/// <param name="a">The start angle. A float expressed in degrees.</param>
/// <param name="b">The end angle. A float expressed in degrees.</param>
/// <param name="t">The interpolation value between the start and end angles.
/// This value is clamped to the range [0, 1].</param>
/// <returns>Returns the interpolated float result between angle a and angle b,
/// based on the interpolation value t.</returns>
public static float LerpAngle(float a, float b, float t)
{
float num = Repeat(b - a, 360f);
if (num > 180f)
{
num -= 360f;
}
return a + num * Clamp01(t);
}
public static int Sign(float value) => MathF.Sign(value);
/// <summary>
/// Returns a value that increments and decrements between zero and the
/// length. It follows the triangle wave formula where the bottom is set to zero
/// and the peak is set to length.
/// </summary>
public static float PingPong(float t, float length)
{
t = Repeat(t, length * 2f);
return length - MathF.Abs(t - length);
}
/// <summary>
/// Moves a value current towards target.
/// </summary>
/// <param name="current">The current value.</param>
/// <param name="target">The value to move towards.</param>
/// <param name="maxDelta">The maximum change applied to the current value.</param>
public static float MoveTowards(float current, float target, float maxDelta)
{
if (MathF.Abs(target - current) <= maxDelta)
{
return target;
}
return current + Sign(target - current) * maxDelta;
}
/// <summary>
/// Calculates the shortest difference between two angles.
/// </summary>
/// <param name="current">The current angle in degrees.</param>
/// <param name="target">The target angle in degrees.</param>
/// <returns>A value between -179 and 180, in degrees.</returns>
public static float DeltaAngle(float current, float target)
{
float num = Repeat(target - current, 360f);
if (num > 180f)
{
num -= 360f;
}
return num;
}
/// <summary>
/// Same as MoveTowards but makes sure the values interpolate correctly when they wrap around 360 degrees.
/// </summary>
public static float MoveTowardsAngle(float current, float target, float maxDelta)
{
float num = DeltaAngle(current, target);
if (0f - maxDelta < num && num < maxDelta)
{
return target;
}
target = current + num;
return MoveTowards(current, target, maxDelta);
}
}

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// Rectangle type /// Rectangle type
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Rectangle public struct Rectangle
{ {
public float X; public float X;
public float Y; public float Y;
@@ -72,7 +72,42 @@ public partial struct Rectangle
} }
} }
public override string ToString() public readonly Vector2 Center
{
get
{
Vector2 center = new Vector2();
center.X = X + (Width / 2.0f);
center.Y = Y + (Height / 2.0f);
return center;
}
}
public readonly void GetIntegerValues(out int x, out int y, out int width, out int height)
{
x = (int)this.X;
y = (int)this.Y;
width = (int)this.Width;
height = (int)this.Height;
}
public void Grow(float growth)
{
X -= growth;
Y -= growth;
Width += growth * 2.0f;
Height += growth * 2.0f;
}
public void Shrink(float shrink)
{
X += shrink;
Y += shrink;
Width -= shrink * 2.0f;
Height -= shrink * 2.0f;
}
public readonly override string ToString()
{ {
return $"{{X:{X} Y:{Y} Width:{Width} Height:{Height}}}"; return $"{{X:{X} Y:{Y} Width:{Width} Height:{Height}}}";
} }

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// RenderBatch type /// RenderBatch type
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct RenderBatch public unsafe struct RenderBatch
{ {
/// <summary> /// <summary>
/// Number of vertex buffers (multi-buffering support) /// Number of vertex buffers (multi-buffering support)
@@ -44,7 +44,7 @@ public unsafe partial struct RenderBatch
/// Dynamic vertex buffers (position + texcoords + colors + indices arrays) /// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct VertexBuffer public unsafe struct VertexBuffer
{ {
/// <summary> /// <summary>
/// Number of elements in the buffer (QUADS) /// Number of elements in the buffer (QUADS)

View File

@@ -6,7 +6,7 @@ namespace Raylib_cs;
/// RenderTexture2D type, for texture rendering /// RenderTexture2D type, for texture rendering
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct RenderTexture2D public struct RenderTexture2D
{ {
/// <summary> /// <summary>
/// OpenGL Framebuffer Object (FBO) id /// OpenGL Framebuffer Object (FBO) id

View File

@@ -76,7 +76,7 @@ public enum ShaderUniformDataType
/// Shader type (generic) /// Shader type (generic)
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Shader public unsafe struct Shader
{ {
/// <summary> /// <summary>
/// Shader program id /// Shader program id

View File

@@ -6,7 +6,7 @@ namespace Raylib_cs;
/// Sound source type /// Sound source type
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Sound public struct Sound
{ {
/// <summary> /// <summary>
/// Audio stream /// Audio stream

View File

@@ -1,4 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Numerics;
namespace Raylib_cs; namespace Raylib_cs;
@@ -102,7 +103,7 @@ public enum CubemapLayout
/// NOTE: Data stored in GPU memory /// NOTE: Data stored in GPU memory
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Texture2D public struct Texture2D
{ {
/// <summary> /// <summary>
/// OpenGL texture id /// OpenGL texture id
@@ -128,4 +129,9 @@ public partial struct Texture2D
/// Data format (PixelFormat type) /// Data format (PixelFormat type)
/// </summary> /// </summary>
public PixelFormat Format; public PixelFormat Format;
/// <summary>
/// Get width and height packed in a Vector2
/// </summary>
public readonly Vector2 Dimensions => new Vector2(Width, Height);
} }

View File

@@ -7,7 +7,7 @@ namespace Raylib_cs;
/// Transform, vertex transformation data /// Transform, vertex transformation data
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public partial struct Transform public struct Transform
{ {
/// <summary> /// <summary>
/// Translation /// Translation
@@ -23,4 +23,14 @@ public partial struct Transform
/// Scale /// Scale
/// </summary> /// </summary>
public Vector3 Scale; public Vector3 Scale;
public void TranslateLocal(Vector3 translation)
{
Translation += Vector3.Transform(translation, Rotation);
}
public void TranslateGlobal(Vector3 translation)
{
Translation += translation;
}
} }

View File

@@ -6,7 +6,7 @@ namespace Raylib_cs;
/// Wave type, defines audio wave data /// Wave type, defines audio wave data
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Wave public unsafe struct Wave
{ {
/// <summary> /// <summary>
/// Number of samples /// Number of samples

View File

@@ -1,5 +1,5 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System;
namespace Raylib_cs; namespace Raylib_cs;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Raylib_cs; namespace Raylib_cs;
@@ -13,8 +12,8 @@ public readonly struct CBool
* which can be later implicitely cast onto any type during usage. * 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 * 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 * Int64 (long) for every CBool instance is.. well, wildly memory-inefficient. Yes,
* process is basically treated as a 0-cost instantiation, but it's better to rely * 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 * on explicit motivation than to blindly trust the runtime judgement on its memory
* management. * management.
* *
@@ -30,7 +29,7 @@ public readonly struct CBool
{ {
this.Value = (sbyte)(value ? 1 : 0); this.Value = (sbyte)(value ? 1 : 0);
} }
public CBool(Int64 value) public CBool(long value)
{ {
this.Value = (sbyte)(value != 0 ? 1 : 0); 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. // Allows for CBools to be implicitely assigned to a native boolean variable.
public static implicit operator bool(CBool x) public static implicit operator bool(CBool x)
{ {
return x.Value != 0 ? true : false; return x.Value != 0;
} }
// Native -> CBool // Native -> CBool
// Allows native booleans to be implicitely constructed into CBools while passing parameters. // Allows native booleans to be implicitely constructed into CBools while passing parameters.
public static implicit operator CBool(bool x) 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). // 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 /* Arithmetic overloads

View File

@@ -22,4 +22,19 @@ public unsafe struct FilePathList
/// Filepaths entries /// Filepaths entries
/// </summary> /// </summary>
public byte** Paths; public byte** Paths;
public string this[uint i]
{
get
{
if (i >= 0 && i < Count)
{
return Marshal.PtrToStringUTF8((System.IntPtr)Paths[i]);
}
else
{
throw new System.IndexOutOfRangeException();
}
}
}
} }

View File

@@ -41,10 +41,10 @@ public static class Utf8StringUtils
return null; return null;
} }
var length = Encoding.UTF8.GetByteCount(text); int length = Encoding.UTF8.GetByteCount(text);
var byteArray = new byte[length + 1]; byte[] byteArray = new byte[length + 1];
var wrote = Encoding.UTF8.GetBytes(text, 0, text.Length, byteArray, 0); int wrote = Encoding.UTF8.GetBytes(text, 0, text.Length, byteArray, 0);
byteArray[wrote] = 0; byteArray[wrote] = 0;
return byteArray; return byteArray;