Watch
2
0
Fork
You've already forked raylib-cs
0

Upgrade Raylib to 6.0 (#337)

* Updated target to Raylib 6 + synced invoke called with the changes in C. [WARNING: Breaking changes!]

* Added severial examples. Corrected towards the correct return type and add utilities to prevent working with pointers

* Additional resources from the Raylib repo.

* Fixed additional pinvokes to match with the new raylib bindings. [Warning breaking changes!]

* Fixing the QOL utils

* Fixing the Mesh struct

* Applying changes after review. Merged resources.LICENSE + raylib-cs.Native.csproj only targets dotnet8

* Updated README to reflect .NET 10 and Raylib 6 compatibility changes.

* Updated shader colors, adjusted car model scale, disabled HDR in SkyboxDemo, and fixed camera mode assignment. Removed unused `Capacity` field in FilePathList struct.

* Improved XML comments for consistency, fixed spacing and formatting across examples, added new resources to `resources.LICENSE`.

* Updated XML comment for `GetDirectoryFileCountEx` to clarify behavior and filtering options.

* Updated and clarified XML comments for methods and parameters, improved naming consistency, and refined shader-related functions. Renamed enums in `Shader.cs` for so it is inline with the upstream.

* Improved XML comments for clarity and consistency in `Model.cs` and `Mesh.cs`, updated method and variable names for better readability, and adjusted logic in span creation methods.

* Corrected XML comment capitalization in `Model.cs`.

---------

Co-authored-by: Meatcorps <info@meatcorps.nl>
This commit is contained in:
Dennis Steffen 2026-05-24 08:21:12 +02:00 committed by GitHub
commit 21d83c60a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
189 changed files with 43644 additions and 380 deletions

View file

@ -181,7 +181,22 @@ public unsafe struct Mesh
#endregion
#region Animation vertex data
#region Skin data for animation
/// <summary>
/// Number of bones (MAX: 256 bones)
/// </summary>
public int BoneCount;
/// <summary>
/// Vertex bone indices, up to 4 bones influence by vertex (skinning) (shader-location = 6)
/// </summary>
public byte* BoneIndices = default;
/// <summary>
/// Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
/// </summary>
public float* BoneWeights = default;
/// <summary>
/// Animated vertex positions (after bones transformations)
@ -193,26 +208,6 @@ public unsafe struct Mesh
/// </summary>
public float* AnimNormals = default;
/// <summary>
/// Vertex bone ids, up to 4 bones influence by vertex (skinning)
/// </summary>
public byte* BoneIds = default;
/// <summary>
/// Vertex bone weight, up to 4 bones influence by vertex (skinning)
/// </summary>
public float* BoneWeights = default;
/// <summary>
/// Bones animated transformation matrices
/// </summary>
public Matrix4x4* BoneMatrices = default;
/// <summary>
/// Number of bones
/// </summary>
public int BoneCount;
#endregion
#region OpenGL identifiers
@ -223,7 +218,7 @@ public unsafe struct Mesh
public uint VaoId = default;
/// <summary>
/// OpenGL Vertex Buffer Objects id (default vertex data, uint[])
/// OpenGL Vertex Buffer Objects id (default vertex data)
/// </summary>
public uint* VboId = default;
@ -263,4 +258,6 @@ public unsafe struct Mesh
public const int VboIdIndexIndices = 6;
#endregion
}

View file

@ -19,8 +19,65 @@ public unsafe struct BoneInfo
/// Bone parent
/// </summary>
public int Parent;
/// <summary>
/// Bone name as string
/// </summary>
public string NameToString()
{
fixed (sbyte* name = Name)
{
return Utf8StringUtils.GetUTF8String(name);
}
}
}
/// <summary>
/// Skeleton, animation bones hierarchy
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct ModelSkeleton
{
/// <summary>
/// Number of bones
/// </summary>
public int BoneCount;
/// <summary>
/// Bones information (skeleton)
/// </summary>
public BoneInfo* Bones;
/// <summary>
/// Bones base transformation (Transform[])
/// </summary>
public Transform* BindPose;
public Span<Transform> BindPoseAsSpan()
{
if (BindPose == null || BoneCount <= 0)
{
return Span<Transform>.Empty;
}
return new Span<Transform>(BindPose, BoneCount);
}
public Span<BoneInfo> BonesAsSpan()
{
if (Bones == null || BoneCount <= 0)
{
return Span<BoneInfo>.Empty;
}
return new Span<BoneInfo>(Bones, BoneCount);
}
}
// Note:
// Anim pose, an array of Transform[]
// typedef Transform *ModelAnimPose; It's just a pointer array.
/// <summary>
/// Model type
/// </summary>
@ -58,92 +115,128 @@ public unsafe struct Model
public int* MeshMaterial;
/// <summary>
/// Number of bones
/// Skeleton for animation
/// </summary>
public int BoneCount;
public ModelSkeleton Skeleton;
//TODO: Span
/// <summary>
/// Bones information (skeleton, BoneInfo *)
/// Current animation pose (Transform[])
/// </summary>
public BoneInfo* Bones;
public Transform* CurrentPose;
//TODO: Span
/// <summary>
/// Bones base transformation (pose, Transform *)
/// Bones animated transformation matrices
/// </summary>
public Transform* BindPose;
public Matrix4x4* BoneMatrices;
/// <summary>
/// Bones animated transformation matrices as span. Based on Skeleton.BoneCount length
/// </summary>
public Span<Matrix4x4> BoneMatricesAsSpan()
{
if (BoneMatrices == null || Skeleton.BoneCount <= 0)
{
return Span<Matrix4x4>.Empty;
}
return new Span<Matrix4x4>(BoneMatrices, Skeleton.BoneCount);
}
/// <summary>
/// Current animation pose as span. Based on Skeleton.BoneCount length
/// </summary>
public Span<Transform> CurrentPoseAsSpan()
{
if (CurrentPose == null || Skeleton.BoneCount <= 0)
{
return Span<Transform>.Empty;
}
return new Span<Transform>(CurrentPose, Skeleton.BoneCount);
}
/// <summary>
/// Mesh material number as span. Based on MaterialCount length
/// </summary>
public Span<int> MeshMaterialAsSpan()
{
if (MeshMaterial == null || MaterialCount <= 0)
{
return Span<int>.Empty;
}
return new Span<int>(MeshMaterial, MaterialCount);
}
/// <summary>
/// Meshes as span. Based on MeshCount length
/// </summary>
public Span<Mesh> MeshesAsSpan()
{
if (Meshes == null || MeshCount <= 0)
{
return Span<Mesh>.Empty;
}
return new Span<Mesh>(Meshes, MeshCount);
}
}
/// <summary>
/// Model animation
/// ModelAnimation, contains a full animation sequence
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct ModelAnimation
{
/// <summary>
/// Animation name (char[32])
/// </summary>
public fixed sbyte Name[32];
/// <summary>
/// Number of bones
/// </summary>
public readonly int BoneCount;
/// <summary>
/// Number of animation frames
/// Number of animation key frames
/// </summary>
public readonly int FrameCount;
public readonly int KeyFrameCount;
/// <summary>
/// Bones information (skeleton, BoneInfo *)
/// Animation sequence keyframe poses [keyframe][pose]
/// </summary>
public readonly BoneInfo* Bones;
public Transform** KeyframePoses;
/// <inheritdoc cref="Bones"/>
public readonly ReadOnlySpan<BoneInfo> BoneInfo => new ReadOnlySpan<BoneInfo>(Bones, BoneCount);
/// <summary>
/// Poses array by frame (Transform **)
/// Animation sequence keyframe poses as span. Based on KeyFrameCount length
/// </summary>
public readonly Transform** FramePoses;
/// <summary>
/// Animation name (char[32])
/// </summary>
public fixed sbyte Name[32];
/// <inheritdoc cref="FramePoses"/>
public readonly FramePosesCollection FramePosesColl => new FramePosesCollection(FramePoses, FrameCount, BoneCount);
public readonly struct FramePosesCollection
public Span<Transform> GetKeyFramePoseAsSpan(int frame)
{
readonly Transform** _framePoses;
readonly int _frameCount;
readonly int _boneCount;
public readonly FramePoses this[int index] => new FramePoses(_framePoses[index], _boneCount);
public readonly Transform this[int index1, int index2] => new FramePoses(_framePoses[index1], _boneCount)[index2];
internal FramePosesCollection(Transform** framePoses, int frameCount, int boneCount)
if (KeyframePoses == null || frame < 0 || frame >= KeyFrameCount)
{
this._framePoses = framePoses;
this._frameCount = frameCount;
this._boneCount = boneCount;
return Span<Transform>.Empty;
}
var pose = KeyframePoses[frame];
if (pose == null || BoneCount <= 0)
{
return Span<Transform>.Empty;
}
return new Span<Transform>(KeyframePoses[frame], KeyFrameCount);
}
/// <summary>
/// Animation name as string
/// </summary>
public string NameToString()
{
fixed (sbyte* name = Name)
{
return Utf8StringUtils.GetUTF8String(name);
}
}
}
public readonly unsafe struct FramePoses
{
readonly Transform* _poses;
readonly int _count;
public readonly ref Transform this[int index] => ref _poses[index];
internal FramePoses(Transform* poses, int count)
{
this._poses = poses;
this._count = count;
}
}

View file

@ -20,6 +20,20 @@ public static unsafe partial class Raylib
SetWindowTitle(str1.AsPointer());
}
/// <summary>Set icon for window (multiple images, RGBA 32bit)</summary>
public static void SetWindowIcons(Image[] images)
{
if (images == null || images.Length == 0)
{
return;
}
fixed (Image* imagesPtr = images)
{
SetWindowIcons(imagesPtr, images.Length);
}
}
/// <summary>Get the human-readable, UTF-8 encoded name of the specified monitor</summary>
public static string GetMonitorName_(int monitor)
{
@ -102,7 +116,7 @@ public static unsafe partial class Raylib
public static long GetFileModTime(string fileName)
{
using AnsiBuffer str1 = fileName.ToAnsiBuffer();
return GetFileModTime(str1.AsPointer());
return GetFileModTime(str1.AsPointer()).Value;
}
/// <summary>Load image from file into CPU memory (RAM)</summary>
@ -112,6 +126,19 @@ public static unsafe partial class Raylib
return LoadImage(str1.AsPointer());
}
/// <summary>Load image sequence from memory buffer</summary>
public static Image LoadImageAnimFromMemory(string fileType, byte[] fileData, out int frames)
{
using AnsiBuffer type = fileType.ToAnsiBuffer();
fixed (byte* data = fileData)
{
int frameCount;
var result = LoadImageAnimFromMemory(type.AsPointer(), data, fileData.Length, &frameCount);
frames = frameCount;
return result;
}
}
/// <summary>Load image from RAW file data</summary>
public static Image LoadImageRaw(string fileName, int width, int height, PixelFormat format, int headerSize)
{
@ -192,7 +219,7 @@ public static unsafe partial class Raylib
/// <summary>Set shader uniform value</summary>
public static void SetShaderValue<T>(Shader shader, int locIndex, T value, ShaderUniformDataType uniformType)
where T : unmanaged
where T : unmanaged
{
SetShaderValue(shader, locIndex, &value, uniformType);
}
@ -244,6 +271,7 @@ public static unsafe partial class Raylib
{
return false;
}
fixed (T* ptr = data)
{
using AnsiBuffer ansiBuffer = fileName.ToAnsiBuffer();
@ -251,6 +279,16 @@ public static unsafe partial class Raylib
}
}
/// <summary>Export data to code (.h), returns true on success</summary>
public static CBool ExportDataAsCode(byte[] data, string fileName)
{
fixed (byte* ptr = data)
{
using AnsiBuffer name = fileName.ToAnsiBuffer();
return ExportDataAsCode(ptr, data.Length, name.AsPointer());
}
}
/// <summary>Load file data as byte array (read)</summary>
public static byte* LoadFileData(string fileName, ref int bytesRead)
{
@ -265,6 +303,13 @@ public static unsafe partial class Raylib
{
int length = 0;
byte* data = LoadFileData(fileName, ref length);
if (data == null)
{
return Array.Empty<byte>();
}
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)data, arr, 0, length);
UnloadFileData(data);
@ -294,6 +339,7 @@ public static unsafe partial class Raylib
{
files[i] = filePathList[i];
}
UnloadDroppedFiles(filePathList);
return files;
@ -409,7 +455,7 @@ public static unsafe partial class Raylib
CBool lockView,
CBool rotateAroundTarget,
CBool rotateUp
)
)
{
fixed (Camera3D* c = &camera)
{
@ -866,7 +912,8 @@ public static unsafe partial class Raylib
}
/// <summary>Draw triangle with interpolated colors within an image</summary>
public static void ImageDrawTriangleEx(ref Image dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
public static void ImageDrawTriangleEx(ref Image dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2,
Color c3)
{
fixed (Image* p = &dst)
{
@ -1085,6 +1132,24 @@ public static unsafe partial class Raylib
}
}
/// <summary>Load model animations from file</summary>
public static Span<ModelAnimation> LoadModelAnimations(string fileName)
{
using AnsiBuffer str1 = fileName.ToAnsiBuffer();
int count;
ModelAnimation* result = LoadModelAnimations(str1.AsPointer(), &count);
return new Span<ModelAnimation>(result, count);
}
public static void UnloadModelAnimations(Span<ModelAnimation> animations)
{
fixed (ModelAnimation* ptr = animations)
{
UnloadModelAnimations(ptr, animations.Length);
}
}
/// <summary>Compute mesh tangents</summary>
public static void GenMeshTangents(ref Mesh mesh)
{
@ -1094,6 +1159,33 @@ public static unsafe partial class Raylib
}
}
/// <summary>Update sound buffer with new data</summary>
public static void UpdateSound<T>(Sound sound, ReadOnlySpan<T> data, int sampleCount) where T : unmanaged
{
fixed (T* dataPtr = data)
{
UpdateSound(sound, dataPtr, sampleCount);
}
}
/// <summary>Update sound buffer with new data</summary>
public static void UpdateSound<T>(Sound sound, ReadOnlySpan<T> data) where T : unmanaged
{
fixed (T* dataPtr = data)
{
UpdateSound(sound, dataPtr, data.Length);
}
}
/// <summary>Update audio stream buffers with data</summary>
public static void UpdateAudioStream<T>(AudioStream sound, ReadOnlySpan<T> data, int frameCount) where T : unmanaged
{
fixed (T* dataPtr = data)
{
UpdateAudioStream(sound, dataPtr, frameCount);
}
}
/// <summary>Convert wave data to desired format</summary>
public static void WaveFormat(ref Wave wave, int sampleRate, int sampleSize, int channels)
{
@ -1214,6 +1306,33 @@ public static unsafe partial class Raylib
DrawTextPro(font, str1.AsPointer(), position, origin, rotation, fontSize, spacing, tint);
}
/// <summary>Draw multiple characters (codepoint)</summary>
public static void DrawTextCodepoints(
Font font,
int[] codepoints,
Vector2 position,
float fontSize,
float spacing,
Color tint
)
{
fixed (int* codepointsPtr = codepoints)
{
DrawTextCodepoints(font, codepointsPtr, codepoints.Length, position, fontSize, spacing, tint);
}
}
/// <summary>Measure string size for Font</summary>
public static Vector2 MeasureTextCodepoints(
Font font, int[] codepoints, float fontSize, float spacing
)
{
fixed (int* codepointsPtr = codepoints)
{
return MeasureTextCodepoints(font, codepointsPtr, codepoints.Length, fontSize, spacing);
}
}
/// <summary>Measure string width for default font</summary>
public static int MeasureText(string text, int fontSize)
{
@ -1484,12 +1603,12 @@ public static unsafe partial class Raylib
public static string GetApplicationDirectoryString()
{
return new string(GetApplicationDirectory());
return Utf8StringUtils.GetUTF8String(GetApplicationDirectory());
}
public static string GetWorkingDirectoryString()
{
return new string(GetWorkingDirectory());
return Utf8StringUtils.GetUTF8String(GetWorkingDirectory());
}
/// <summary>
@ -1511,6 +1630,7 @@ public static unsafe partial class Raylib
{
output[i] = sequence[i];
}
UnloadRandomSequence(sequence);
return output;
}
@ -1536,6 +1656,7 @@ public static unsafe partial class Raylib
float norm = (float)val / (float)maxi;
output[i] = Raymath.Lerp(min, max, norm);
}
return output;
}
@ -1549,6 +1670,373 @@ public static unsafe partial class Raylib
SaveFileText(fileBuffer.AsPointer(), textBuffer.AsPointer());
}
/// <summary>Rename file (if exists)</summary>
public static int FileRename(string filename, string fileRename)
{
using AnsiBuffer fileBuffer = filename.ToAnsiBuffer();
using AnsiBuffer textBuffer = fileRename.ToAnsiBuffer();
return FileRename(fileBuffer.AsPointer(), textBuffer.AsPointer());
}
/// <summary>Remove file (if exists)</summary>
public static int FileRemove(string filename)
{
using AnsiBuffer fileBuffer = filename.ToAnsiBuffer();
return FileRemove(fileBuffer.AsPointer());
}
/// <summary>Copy file from one path to another, dstPath created if it doesn't exist</summary>
public static int FileCopy(string srcPath, string dstPath)
{
using AnsiBuffer srcBuffer = srcPath.ToAnsiBuffer();
using AnsiBuffer dstBuffer = dstPath.ToAnsiBuffer();
return FileCopy(srcBuffer.AsPointer(), dstBuffer.AsPointer());
}
/// <summary>Move file from one path to another, dstPath created if it doesn't exist</summary>
public static int FileMove(string srcPath, string dstPath)
{
using AnsiBuffer srcBuffer = srcPath.ToAnsiBuffer();
using AnsiBuffer dstBuffer = dstPath.ToAnsiBuffer();
return FileMove(srcBuffer.AsPointer(), dstBuffer.AsPointer());
}
/// <summary>Replace text in an existing file</summary>
public static int FileTextReplace(string fileName, string search, string replacement)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
using AnsiBuffer searchBuffer = search.ToAnsiBuffer();
using AnsiBuffer replaceBuffer = replacement.ToAnsiBuffer();
return FileTextReplace(fileBuffer.AsPointer(), searchBuffer.AsPointer(), replaceBuffer.AsPointer());
}
/// <summary>Find text in existing file</summary>
public static int FileTextFindIndex(string fileName, string search)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
using AnsiBuffer searchBuffer = search.ToAnsiBuffer();
return FileTextFindIndex(fileBuffer.AsPointer(), searchBuffer.AsPointer());
}
/// <summary>Check if file exists</summary>
public static CBool FileExists(string fileName)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
return FileExists(fileBuffer.AsPointer());
}
/// <summary>Check if a directory path exists</summary>
public static CBool DirectoryExists(string dirPath)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
return DirectoryExists(dirBuffer.AsPointer());
}
/// <summary>Get file length in bytes</summary>
public static int GetFileLength(string fileName)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
return GetFileLength(fileBuffer.AsPointer());
}
/// <summary>Get string to extension for a filename string (includes dot: '.png')</summary>
public static string GetFileExtension(string fileName)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
return Utf8StringUtils.GetUTF8String(GetFileExtension(fileBuffer.AsPointer()));
}
/// <summary>Get string to filename for a path string</summary>
public static string GetFileName(string fileName)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
return Utf8StringUtils.GetUTF8String(GetFileName(fileBuffer.AsPointer()));
}
/// <summary>Get filename string without extension </summary>
public static string GetFileNameWithoutExt(string fileName)
{
using AnsiBuffer fileBuffer = fileName.ToAnsiBuffer();
return Utf8StringUtils.GetUTF8String(GetFileNameWithoutExt(fileBuffer.AsPointer()));
}
/// <summary>Get full path for a given fileName with path</summary>
public static string GetDirectoryPath(string filePath)
{
using AnsiBuffer fileBuffer = filePath.ToAnsiBuffer();
return Utf8StringUtils.GetUTF8String(GetDirectoryPath(fileBuffer.AsPointer()));
}
/// <summary>Get previous directory path for a given path</summary>
public static string GetPrevDirectoryPath(string dirPath)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
return Utf8StringUtils.GetUTF8String(GetPrevDirectoryPath(dirBuffer.AsPointer()));
}
/// <summary>Get current working directory</summary>
public static string GetWorkingDirectoryAsString()
{
return Utf8StringUtils.GetUTF8String(GetWorkingDirectory());
}
/// <summary>Get the directory of the running application</summary>
public static string GetApplicationDirectoryAsString()
{
return Utf8StringUtils.GetUTF8String(GetApplicationDirectory());
}
/// <summary>Change working directory, return true on success</summary>
public static CBool ChangeDirectory(string dirPath)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
return ChangeDirectory(dirBuffer.AsPointer());
}
/// <summary>Check if a given path is a file or a directory</summary>
public static CBool IsPathFile(string path)
{
using AnsiBuffer pathBuffer = path.ToAnsiBuffer();
return IsPathFile(pathBuffer.AsPointer());
}
/// <summary>Load directory filepaths</summary>
public static FilePathList LoadDirectoryFiles(string dirPath)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
return LoadDirectoryFiles(dirBuffer.AsPointer());
}
/// <summary>Get the file count in a directory</summary>
public static int GetDirectoryFileCount(string dirPath)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
return GetDirectoryFileCount(dirBuffer.AsPointer());
}
/// <summary>Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result</summary>
public static int GetDirectoryFileCountEx(string dirPath, string filter, CBool scanSubdirs)
{
using AnsiBuffer dirBuffer = dirPath.ToAnsiBuffer();
using AnsiBuffer filterBuffer = filter.ToAnsiBuffer();
return GetDirectoryFileCountEx(dirBuffer.AsPointer(), filterBuffer.AsPointer(), scanSubdirs);
}
/// <summary>Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"</summary>
public static FilePathList LoadDirectoryFilesEx(string basePath, string filter, CBool scanSubDirs)
{
using AnsiBuffer baseBuffer = basePath.ToAnsiBuffer();
using AnsiBuffer filterBuffer = filter.ToAnsiBuffer();
return LoadDirectoryFilesEx(baseBuffer.AsPointer(), filterBuffer.AsPointer(), scanSubDirs);
}
/// <summary>Compress data (DEFLATE algorithm)</summary>
public static byte[] CompressData(byte[] data)
{
fixed (byte* dataPtr = data)
{
int compressedSize;
var compressedPtr = CompressData(dataPtr, data.Length, &compressedSize);
if (compressedPtr == null || compressedSize <= 0)
{
return Array.Empty<byte>();
}
try
{
var result = new byte[compressedSize];
fixed (byte* resultPtr = result)
{
Buffer.MemoryCopy(
compressedPtr,
resultPtr,
compressedSize,
compressedSize
);
}
return result;
}
finally
{
MemFree(compressedPtr);
}
}
}
/// <summary>Decompress data (DEFLATE algorithm)</summary>
public static byte[] DecompressData(byte[] data)
{
fixed (byte* dataPtr = data)
{
int dataSize;
var compressedPtr = DecompressData(dataPtr, data.Length, &dataSize);
if (compressedPtr == null || dataSize <= 0)
{
return Array.Empty<byte>();
}
try
{
var result = new byte[dataSize];
fixed (byte* resultPtr = result)
{
Buffer.MemoryCopy(
compressedPtr,
resultPtr,
dataSize,
dataSize
);
}
return result;
}
finally
{
MemFree(compressedPtr);
}
}
}
/// <summary>Encode data to Base64 string</summary>
public static byte[] EncodeDataBase64(byte[] data)
{
fixed (byte* dataPtr = data)
{
int outputSize;
var compressedPtr = EncodeDataBase64(dataPtr, data.Length, &outputSize);
if (compressedPtr == null || outputSize <= 0)
{
return Array.Empty<byte>();
}
try
{
var result = new byte[outputSize];
fixed (byte* resultPtr = result)
{
Buffer.MemoryCopy(
compressedPtr,
resultPtr,
outputSize,
outputSize
);
}
return result;
}
finally
{
MemFree(compressedPtr);
}
}
}
/// <summary>Decode data to Base64 string</summary>
public static byte[] DecodeDataBase64(string data)
{
using Utf8Buffer ptr = data.ToUtf8Buffer();
int outputSize;
var compressedPtr = DecodeDataBase64(ptr.AsPointer(), &outputSize);
if (compressedPtr == null || outputSize <= 0)
{
return Array.Empty<byte>();
}
try
{
var result = new byte[outputSize];
fixed (byte* resultPtr = result)
{
Buffer.MemoryCopy(
compressedPtr,
resultPtr,
outputSize,
outputSize
);
}
return result;
}
finally
{
MemFree(compressedPtr);
}
}
/// <summary>Compute CRC32 hash code</summary>
public static uint ComputeCRC32(byte[] data)
{
fixed (byte* dataPtr = data)
{
return ComputeCRC32(dataPtr, data.Length);
}
}
/// <summary>Compute MD5 hash code, returns uint[4] array</summary>
public static uint[] ComputeMD5(byte[] data)
{
fixed (byte* dataPtr = data)
{
var result = ComputeMD5(dataPtr, data.Length);
return
[
result[0],
result[1],
result[2],
result[3],
];
}
}
/// <summary>Compute SHA1 hash code, returns uint[5] array</summary>
public static uint[] ComputeSHA1(byte[] data)
{
fixed (byte* dataPtr = data)
{
var result = ComputeSHA1(dataPtr, data.Length);
return
[
result[0],
result[1],
result[2],
result[3],
result[4],
];
}
}
/// <summary>Compute SHA256 hash code, returns int[8] (32 bytes)</summary>
public static uint[] ComputeSHA256(byte[] data)
{
fixed (byte* dataPtr = data)
{
var result = ComputeSHA256(dataPtr, data.Length);
return
[
result[0],
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
result[7],
];
}
}
/// <summary>
/// Loads text from a file, reads it, saves it, unloads the file, and returns the loaded text.
/// </summary>
@ -1569,4 +2057,5 @@ public static unsafe partial class Raylib
center.Y = GetScreenHeight() / 2.0f;
return center;
}
}

View file

@ -35,7 +35,8 @@ public enum ShaderLocationIndex
MapBrdf,
VertexBoneIds,
VertexBoneWeights,
BoneMatrices,
MatrixBoneTransforms,
VertexInstanceTransform,
MapDiffuse = MapAlbedo,
MapSpecular = MapMetalness,

View file

@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace Raylib_cs;
@ -8,11 +9,6 @@ namespace Raylib_cs;
[StructLayout(LayoutKind.Sequential)]
public unsafe struct FilePathList
{
/// <summary>
/// Filepaths max entries
/// </summary>
public uint Capacity;
/// <summary>
/// Filepaths entries count
/// </summary>

View file

@ -21,6 +21,11 @@ public readonly ref struct Utf8Buffer
return (sbyte*)_data.ToPointer();
}
public unsafe byte* AsBytePointer()
{
return (byte*)_data.ToPointer();
}
public void Dispose()
{
Marshal.ZeroFreeCoTaskMemUTF8(_data);