Automatically generate functions that return their slice length, where possible

This commit is contained in:
Nikolas 2025-03-30 19:29:51 +02:00
parent c30197911a
commit d6c77762cb
No known key found for this signature in database
GPG Key ID: E95F679E3CDD9784
4 changed files with 216 additions and 296 deletions

View File

@ -23,17 +23,93 @@ ZIGGIFY = {
"c_uint": "u32"
}
IGNORE_TYPES = [
"[*c]Color",
"[*c]GlyphInfo",
"[*c]c_int",
"[*c]c_uint",
"[*c][*c]u8",
"[*c][*c]const u8",
"[*c]Material",
"[*c]ModelAnimation",
"[*c]f32",
IGNORE_C_TYPE = [
"rlGetShaderLocsDefault",
]
TRIVIAL_SIZE = [
"LoadFileData",
"CompressData",
"DecompressData",
"EncodeDataBase64",
"DecodeDataBase64",
"ExportImageToMemory",
"LoadImagePalette",
"LoadCodepoints",
"TextSplit",
#"LoadMaterials",
"LoadModelAnimations",
]
HAS_ERROR = TRIVIAL_SIZE
MANUAL = [
"TextFormat",
"TraceLog",
"LoadShader",
"LoadRandomSequence",
"ExportDataAsCode",
"SaveFileData",
"LoadImage",
"LoadImageRaw",
"LoadImageAnim",
"LoadImageFromTexture",
"LoadImageFromScreen",
"LoadImageFromMemory",
"LoadImageColors",
"LoadMaterialDefault",
"LoadMaterials", # todo: Make this automatic, by adding a IsXValid check in this script
"LoadModel",
"LoadModelFromMesh",
"LoadTexture",
"LoadTextureFromImage",
"LoadTextureCubemap",
"LoadRenderTexture",
"LoadWave",
"LoadWaveSamples",
"LoadSound",
"LoadMusicStream",
"LoadAudioStream",
"DrawMeshInstanced",
"UnloadModelAnimations",
"ComputeCRC32",
"ComputeMD5",
"ComputeSHA1",
"SetWindowIcons",
"CheckCollisionPointPoly",
"ColorToInt",
"GetFontDefault",
"LoadFont",
"LoadFontEx",
"LoadFontFromImage",
"LoadFontData",
"ImageText",
"ImageTextEx",
"GenImageFontAtlas",
"UnloadFontData",
"DrawTextCodepoints",
"LoadUTF8",
"TextJoin",
"DrawLineStrip",
"DrawTriangleFan",
"DrawTriangleStrip",
"DrawTriangleStrip3D",
"GuiTabBar",
"GuiListViewEx",
"GuiPanel",
"GuiScrollPanel",
"DrawSplineLinear",
"DrawSplineBasis",
"DrawSplineCatmullRom",
"DrawSplineBezierQuadratic",
"DrawSplineBezierCubic",
"ImageKernelConvolution",
"GuiGetIcons",
"GuiLoadIcons",
"GuiSetStyle",
"GuiGetStyle"
]
# Some C types have a different sizes on different systems and Zig
# knows that so we tell it to get the system specific size for us.
def c_to_zig_type(c: str) -> str:
@ -47,7 +123,9 @@ def c_to_zig_type(c: str) -> str:
return const + c
def ziggify_type(name: str, t: str, func_name) -> str:
def ziggify_type(name: str, t: str, func_name: str) -> str:
if func_name in IGNORE_C_TYPE:
return t
NO_STRINGS = ["data", "fileData", "compData"]
single = [
@ -65,7 +143,7 @@ def ziggify_type(name: str, t: str, func_name) -> str:
"data", "compData", "points", "fileData", "colors", "pixels",
"fontChars", "chars", "recs", "codepoints", "textList", "transforms",
"animations", "samples", "LoadImageColors", "LoadImagePalette",
"LoadFontData", "LoadCodepoints", "TextSplit", "LoadMaterials",
"LoadFontData", "LoadCodepoints", "LoadMaterials",
"LoadModelAnimations", "LoadWaveSamples", "images",
"LoadRandomSequence", "sequence", "kernel", "GlyphInfo", "glyphs", "glyphRecs",
"matf", "rlGetShaderLocsDefault", "locs", "GuiGetIcons", "GuiLoadIcons"
@ -76,7 +154,7 @@ def ziggify_type(name: str, t: str, func_name) -> str:
return "[][:0]const u8"
if t.startswith("[*c]") and name not in single and name not in multi:
if (t == "[*c]const u8" or t == "[*c]u8") and name not in NO_STRINGS: # Strings are multis.
if (t == "[*c]const u8" or t == "[*c]u8" or name == "TextSplit") and name not in NO_STRINGS: # Strings are multis.
string = True
else:
raise ValueError(f"{t} {name} not classified")
@ -84,7 +162,9 @@ def ziggify_type(name: str, t: str, func_name) -> str:
pre = ""
while t.startswith("[*c]"):
t = t[4:]
if string and not t.startswith("[*c]"):
if func_name in TRIVIAL_SIZE and not pre:
pre += "[]"
elif string and not t.startswith("[*c]"):
pre += "[:0]"
elif name in single:
pre += "*"
@ -94,7 +174,11 @@ def ziggify_type(name: str, t: str, func_name) -> str:
if t in ZIGGIFY:
t = ZIGGIFY[t]
return pre + t
error = ""
if name in HAS_ERROR:
error = "RaylibError!"
return error + pre + t
def add_namespace_to_type(t: str) -> str:
@ -119,23 +203,20 @@ def add_namespace_to_type(t: str) -> str:
return pre + t
def make_return_cast(source_type: str, dest_type: str, inner: str) -> str:
if source_type == dest_type:
def make_return_cast(func_name: str, source_type: str, dest_type: str, inner: str) -> str:
if source_type == dest_type or func_name in IGNORE_C_TYPE:
return inner
if "ExportImageToMemory" in inner:
return f"{inner}[0..@as(usize, @intCast(fileSize.*))]"
if source_type.startswith("[*c][*c]"):
inner = f"@as([*][:0]{source_type[8:]}, @ptrCast({inner}))"
if func_name in TRIVIAL_SIZE:
return f"{inner}[0..@as(usize, @intCast(_len))]"
if source_type in ["[*c]const u8", "[*c]u8"]:
return f"std.mem.span({inner})"
if source_type in ZIGGIFY:
return f"@as({dest_type}, {inner})"
# These all have to be done manually because their sizes depend on the
# function arguments.
if source_type in IGNORE_TYPES:
return None
else:
raise ValueError(f"Don't know what to do {source_type} {dest_type} {inner}")
raise ValueError(f"Don't know what to do with '{func_name}': {source_type} {dest_type} {inner}")
def fix_pointer(name: str, t: str):
@ -329,87 +410,34 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
zig_name = convert_name_case(func_name)
# TODO: Ziggify return type
func_prelude = ""
if func_name in TRIVIAL_SIZE:
zig_arguments.pop()
zig_call_args[-1] = "@as([*c]c_int, @ptrCast(&_len))"
func_prelude = "var _len: i32 = 0;\n "
zig_arguments = ", ".join(zig_arguments)
zig_call_args = ", ".join(zig_call_args)
manual = [
"TextFormat",
"TraceLog",
"LoadShader",
"ExportDataAsCode",
"LoadFileData",
"SaveFileData",
"LoadImage",
"LoadImageRaw",
"LoadImageAnim",
"LoadImageFromTexture",
"LoadImageFromScreen",
"LoadImageFromMemory",
"LoadMaterialDefault",
"LoadMaterials",
"LoadModel",
"LoadModelFromMesh",
"LoadTexture",
"LoadTextureFromImage",
"LoadTextureCubemap",
"LoadRenderTexture",
"LoadWave",
"LoadSound",
"LoadMusicStream",
"LoadAudioStream",
"DrawMeshInstanced",
"UnloadModelAnimations",
"CompressData",
"DecompressData",
"EncodeDataBase64",
"DecodeDataBase64",
"ComputeCRC32",
"ComputeMD5",
"ComputeSHA1",
"SetWindowIcons",
"CheckCollisionPointPoly",
"ColorToInt",
"GetFontDefault",
"LoadFont",
"LoadFontEx",
"LoadFontFromImage",
"ImageText",
"ImageTextEx",
"GenImageFontAtlas",
"UnloadFontData",
"DrawTextCodepoints",
"LoadUTF8",
"TextJoin",
"DrawLineStrip",
"DrawTriangleFan",
"DrawTriangleStrip",
"DrawTriangleStrip3D",
"GuiTabBar",
"GuiListViewEx",
"GuiPanel",
"GuiScrollPanel",
"DrawSplineLinear",
"DrawSplineBasis",
"DrawSplineCatmullRom",
"DrawSplineBezierQuadratic",
"DrawSplineBezierCubic",
"ImageKernelConvolution",
"GuiSetStyle",
"GuiGetStyle"
]
if func_name in manual or "FromMemory" in func_name:
if func_name in MANUAL or "FromMemory" in func_name:
continue
inner = f"cdef.{func_name}({zig_call_args})"
if func_name in TRIVIAL_SIZE:
func_prelude += f"const _ptr = {inner};\n if (_ptr == 0) return RaylibError.{func_name};\n "
inner = "_ptr"
zig_return = ziggify_type(func_name, return_type, func_name)
return_cast = make_return_cast(return_type, zig_return, f"cdef.{func_name}({zig_call_args})")
return_cast = make_return_cast(func_name, return_type, zig_return, inner)
if return_cast:
zig_funcs.append(
inline_comment +
f"pub fn {zig_name}({zig_arguments}) {zig_return}" +
" {\n " +
func_prelude +
("return " if zig_return != "void" else "") +
return_cast + ";"
"\n}"

View File

@ -14,11 +14,17 @@ test {
pub const RaylibError = error{
LoadFileData,
CompressData,
DecompressData,
EncodeDataBase64,
DecodeDataBase64,
ExportImageToMemory,
LoadImageColors,
LoadImagePalette,
LoadFont,
LoadFontData,
LoadCodepoints,
TextSplit,
LoadMaterial,
LoadMaterials,
LoadModelAnimations,
@ -2032,19 +2038,6 @@ pub fn loadRandomSequence(count: u32, min: i32, max: i32) []i32 {
return res;
}
/// Load file data as byte array (read)
pub fn loadFileData(fileName: [:0]const u8) RaylibError![]u8 {
var bytesRead: i32 = 0;
var res: []u8 = undefined;
const ptr = cdef.LoadFileData(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&bytesRead)));
if (ptr == 0) return RaylibError.LoadFileData;
res.ptr = @as([*]u8, @ptrCast(ptr));
res.len = @as(usize, @intCast(bytesRead));
return res;
}
/// Save data to file from byte array (write), returns true on success
pub fn saveFileData(fileName: [:0]const u8, data: []u8) bool {
return cdef.SaveFileData(@as([*c]const u8, @ptrCast(fileName)), @as(*anyopaque, @ptrCast(data.ptr)), @as(c_int, @intCast(data.len)));
@ -2055,42 +2048,6 @@ pub fn exportDataAsCode(data: []const u8, fileName: [:0]const u8) bool {
return cdef.ExportDataAsCode(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]const u8, @ptrCast(fileName)));
}
/// Compress data (DEFLATE algorithm), memory must be MemFree()
pub fn compressData(data: []const u8) []u8 {
var compDataSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.CompressData(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]c_int, @ptrCast(&compDataSize)));
res.len = @as(usize, @intCast(compDataSize));
return res;
}
/// Decompress data (DEFLATE algorithm), memory must be MemFree()
pub fn decompressData(compData: []const u8) []u8 {
var dataSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.DecompressData(@as([*c]const u8, @ptrCast(compData)), @as(c_int, @intCast(compData.len)), @as([*c]c_int, @ptrCast(&dataSize)));
res.len = @as(usize, @intCast(dataSize));
return res;
}
/// Encode data to Base64 string, memory must be MemFree()
pub fn encodeDataBase64(data: []const u8) []u8 {
var outputSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.EncodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]c_int, @ptrCast(&outputSize)));
res.len = @as(usize, @intCast(outputSize));
return res;
}
/// Decode Base64 string data, memory must be MemFree()
pub fn decodeDataBase64(data: []const u8) []u8 {
var outputSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.DecodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as([*c]c_int, @ptrCast(&outputSize)));
res.len = @as(usize, @intCast(outputSize));
return res;
}
pub fn computeCRC32(data: []u8) u32 {
return cdef.ComputeCRC32(@as([*c]u8, @ptrCast(data)), @as(c_int, @intCast(data.len)));
}
@ -2181,19 +2138,6 @@ pub fn loadImageColors(image: Image) RaylibError![]Color {
return res;
}
/// Load colors palette from image as a Color array (RGBA - 32bit)
pub fn loadImagePalette(image: Image, maxPaletteSize: i32) RaylibError![]Color {
var colorCount: i32 = 0;
var res: []Color = undefined;
const ptr = cdef.LoadImagePalette(image, @as(c_int, maxPaletteSize), @as([*c]c_int, @ptrCast(&colorCount)));
if (ptr == 0) return RaylibError.LoadImagePalette;
res.ptr = @as([*]Color, @ptrCast(ptr));
res.len = @as(usize, @intCast(colorCount));
return res;
}
/// Load texture from file into GPU memory (VRAM)
pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D {
const texture = cdef.LoadTexture(@as([*c]const u8, @ptrCast(fileName)));
@ -2290,22 +2234,6 @@ pub fn loadFontData(fileData: []const u8, fontSize: i32, fontChars: []i32, ty: F
return res;
}
/// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
pub fn loadCodepoints(text: [:0]const u8) RaylibError![]i32 {
if (@sizeOf(c_int) != @sizeOf(i32)) {
@compileError("Can't cast pointer to c_int array to i32 because they don't have the same size");
}
var count: i32 = 0;
var res: []i32 = undefined;
const ptr = cdef.LoadCodepoints(@as([*c]const u8, @ptrCast(text)), @as([*c]c_int, @ptrCast(&count)));
if (ptr == 0) return RaylibError.LoadCodepoints;
res.ptr = @as([*]i32, @ptrCast(ptr));
res.len = @as(usize, @intCast(count));
return res;
}
/// Text formatting with variables (sprintf() style)
pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 {
comptime {
@ -2342,15 +2270,6 @@ pub fn traceLog(logLevel: TraceLogLevel, text: [:0]const u8, args: anytype) void
@call(.auto, cdef.TraceLog, .{ logLevel, @as([*c]const u8, @ptrCast(text)) } ++ args);
}
/// Split text into multiple strings
pub fn textSplit(text: [:0]const u8, delimiter: u8) [][:0]const u8 {
var count: i32 = 0;
var res: [][:0]const u8 = undefined;
res.ptr = @as([*][:0]const u8, @ptrCast(cdef.TextSplit(@as([*c]const u8, @ptrCast(text)), delimiter, @as([*c]c_int, @ptrCast(&count)))));
res.len = @as(usize, @intCast(count));
return res;
}
/// Draw multiple mesh instances with material and different transforms
pub fn drawMeshInstanced(mesh: Mesh, material: Material, transforms: []const Matrix) void {
cdef.DrawMeshInstanced(mesh, material, @as([*c]const Matrix, @ptrCast(transforms)), @as(c_int, @intCast(transforms.len)));
@ -2396,19 +2315,6 @@ pub fn loadModelFromMesh(mesh: Mesh) RaylibError!Model {
return if (isValid) model else RaylibError.LoadModel;
}
/// Load model animations from file
pub fn loadModelAnimations(fileName: [:0]const u8) RaylibError![]ModelAnimation {
var animCount: i32 = 0;
var res: []ModelAnimation = undefined;
const ptr = cdef.LoadModelAnimations(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&animCount)));
if (ptr == 0) return RaylibError.LoadModelAnimations;
res.ptr = @as([*]ModelAnimation, @ptrCast(ptr));
res.len = @as(usize, @intCast(animCount));
return res;
}
/// Unload animation data
pub fn unloadModelAnimations(animations: []ModelAnimation) void {
cdef.UnloadModelAnimations(@as([*c]ModelAnimation, @ptrCast(animations)), @as(c_int, @intCast(animations.len)));

View File

@ -14,11 +14,17 @@ test {
pub const RaylibError = error{
LoadFileData,
CompressData,
DecompressData,
EncodeDataBase64,
DecodeDataBase64,
ExportImageToMemory,
LoadImageColors,
LoadImagePalette,
LoadFont,
LoadFontData,
LoadCodepoints,
TextSplit,
LoadMaterial,
LoadMaterials,
LoadModelAnimations,
@ -2032,19 +2038,6 @@ pub fn loadRandomSequence(count: u32, min: i32, max: i32) []i32 {
return res;
}
/// Load file data as byte array (read)
pub fn loadFileData(fileName: [:0]const u8) RaylibError![]u8 {
var bytesRead: i32 = 0;
var res: []u8 = undefined;
const ptr = cdef.LoadFileData(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&bytesRead)));
if (ptr == 0) return RaylibError.LoadFileData;
res.ptr = @as([*]u8, @ptrCast(ptr));
res.len = @as(usize, @intCast(bytesRead));
return res;
}
/// Save data to file from byte array (write), returns true on success
pub fn saveFileData(fileName: [:0]const u8, data: []u8) bool {
return cdef.SaveFileData(@as([*c]const u8, @ptrCast(fileName)), @as(*anyopaque, @ptrCast(data.ptr)), @as(c_int, @intCast(data.len)));
@ -2055,42 +2048,6 @@ pub fn exportDataAsCode(data: []const u8, fileName: [:0]const u8) bool {
return cdef.ExportDataAsCode(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]const u8, @ptrCast(fileName)));
}
/// Compress data (DEFLATE algorithm), memory must be MemFree()
pub fn compressData(data: []const u8) []u8 {
var compDataSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.CompressData(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]c_int, @ptrCast(&compDataSize)));
res.len = @as(usize, @intCast(compDataSize));
return res;
}
/// Decompress data (DEFLATE algorithm), memory must be MemFree()
pub fn decompressData(compData: []const u8) []u8 {
var dataSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.DecompressData(@as([*c]const u8, @ptrCast(compData)), @as(c_int, @intCast(compData.len)), @as([*c]c_int, @ptrCast(&dataSize)));
res.len = @as(usize, @intCast(dataSize));
return res;
}
/// Encode data to Base64 string, memory must be MemFree()
pub fn encodeDataBase64(data: []const u8) []u8 {
var outputSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.EncodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as(c_int, @intCast(data.len)), @as([*c]c_int, @ptrCast(&outputSize)));
res.len = @as(usize, @intCast(outputSize));
return res;
}
/// Decode Base64 string data, memory must be MemFree()
pub fn decodeDataBase64(data: []const u8) []u8 {
var outputSize: i32 = 0;
var res: []u8 = undefined;
res.ptr = cdef.DecodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as([*c]c_int, @ptrCast(&outputSize)));
res.len = @as(usize, @intCast(outputSize));
return res;
}
pub fn computeCRC32(data: []u8) u32 {
return cdef.ComputeCRC32(@as([*c]u8, @ptrCast(data)), @as(c_int, @intCast(data.len)));
}
@ -2181,19 +2138,6 @@ pub fn loadImageColors(image: Image) RaylibError![]Color {
return res;
}
/// Load colors palette from image as a Color array (RGBA - 32bit)
pub fn loadImagePalette(image: Image, maxPaletteSize: i32) RaylibError![]Color {
var colorCount: i32 = 0;
var res: []Color = undefined;
const ptr = cdef.LoadImagePalette(image, @as(c_int, maxPaletteSize), @as([*c]c_int, @ptrCast(&colorCount)));
if (ptr == 0) return RaylibError.LoadImagePalette;
res.ptr = @as([*]Color, @ptrCast(ptr));
res.len = @as(usize, @intCast(colorCount));
return res;
}
/// Load texture from file into GPU memory (VRAM)
pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D {
const texture = cdef.LoadTexture(@as([*c]const u8, @ptrCast(fileName)));
@ -2290,22 +2234,6 @@ pub fn loadFontData(fileData: []const u8, fontSize: i32, fontChars: []i32, ty: F
return res;
}
/// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
pub fn loadCodepoints(text: [:0]const u8) RaylibError![]i32 {
if (@sizeOf(c_int) != @sizeOf(i32)) {
@compileError("Can't cast pointer to c_int array to i32 because they don't have the same size");
}
var count: i32 = 0;
var res: []i32 = undefined;
const ptr = cdef.LoadCodepoints(@as([*c]const u8, @ptrCast(text)), @as([*c]c_int, @ptrCast(&count)));
if (ptr == 0) return RaylibError.LoadCodepoints;
res.ptr = @as([*]i32, @ptrCast(ptr));
res.len = @as(usize, @intCast(count));
return res;
}
/// Text formatting with variables (sprintf() style)
pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 {
comptime {
@ -2342,15 +2270,6 @@ pub fn traceLog(logLevel: TraceLogLevel, text: [:0]const u8, args: anytype) void
@call(.auto, cdef.TraceLog, .{ logLevel, @as([*c]const u8, @ptrCast(text)) } ++ args);
}
/// Split text into multiple strings
pub fn textSplit(text: [:0]const u8, delimiter: u8) [][:0]const u8 {
var count: i32 = 0;
var res: [][:0]const u8 = undefined;
res.ptr = @as([*][:0]const u8, @ptrCast(cdef.TextSplit(@as([*c]const u8, @ptrCast(text)), delimiter, @as([*c]c_int, @ptrCast(&count)))));
res.len = @as(usize, @intCast(count));
return res;
}
/// Draw multiple mesh instances with material and different transforms
pub fn drawMeshInstanced(mesh: Mesh, material: Material, transforms: []const Matrix) void {
cdef.DrawMeshInstanced(mesh, material, @as([*c]const Matrix, @ptrCast(transforms)), @as(c_int, @intCast(transforms.len)));
@ -2396,19 +2315,6 @@ pub fn loadModelFromMesh(mesh: Mesh) RaylibError!Model {
return if (isValid) model else RaylibError.LoadModel;
}
/// Load model animations from file
pub fn loadModelAnimations(fileName: [:0]const u8) RaylibError![]ModelAnimation {
var animCount: i32 = 0;
var res: []ModelAnimation = undefined;
const ptr = cdef.LoadModelAnimations(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&animCount)));
if (ptr == 0) return RaylibError.LoadModelAnimations;
res.ptr = @as([*]ModelAnimation, @ptrCast(ptr));
res.len = @as(usize, @intCast(animCount));
return res;
}
/// Unload animation data
pub fn unloadModelAnimations(animations: []ModelAnimation) void {
cdef.UnloadModelAnimations(@as([*c]ModelAnimation, @ptrCast(animations)), @as(c_int, @intCast(animations.len)));
@ -3131,6 +3037,14 @@ pub fn setSaveFileTextCallback(callback: SaveFileTextCallback) void {
cdef.SetSaveFileTextCallback(callback);
}
/// Load file data as byte array (read)
pub fn loadFileData(fileName: []const u8) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.LoadFileData(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.LoadFileData;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Unload file data allocated by LoadFileData()
pub fn unloadFileData(data: []u8) void {
cdef.UnloadFileData(@as([*c]u8, @ptrCast(data)));
@ -3261,6 +3175,38 @@ pub fn getFileModTime(fileName: [:0]const u8) i64 {
return @as(i64, cdef.GetFileModTime(@as([*c]const u8, @ptrCast(fileName))));
}
/// Compress data (DEFLATE algorithm), memory must be MemFree()
pub fn compressData(data: []const u8, dataSize: i32) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.CompressData(@as([*c]const u8, @ptrCast(data)), @as(c_int, dataSize), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.CompressData;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Decompress data (DEFLATE algorithm), memory must be MemFree()
pub fn decompressData(compData: []const u8, compDataSize: i32) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.DecompressData(@as([*c]const u8, @ptrCast(compData)), @as(c_int, compDataSize), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.DecompressData;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Encode data to Base64 string, memory must be MemFree()
pub fn encodeDataBase64(data: []const u8, dataSize: i32) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.EncodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as(c_int, dataSize), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.EncodeDataBase64;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Decode Base64 string data, memory must be MemFree()
pub fn decodeDataBase64(data: []const u8) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.DecodeDataBase64(@as([*c]const u8, @ptrCast(data)), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.DecodeDataBase64;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
pub fn loadAutomationEventList(fileName: [:0]const u8) AutomationEventList {
return cdef.LoadAutomationEventList(@as([*c]const u8, @ptrCast(fileName)));
@ -3847,8 +3793,11 @@ pub fn exportImage(image: Image, fileName: [:0]const u8) bool {
}
/// Export image to memory buffer
pub fn exportImageToMemory(image: Image, fileType: [:0]const u8, fileSize: *i32) [:0]u8 {
return cdef.ExportImageToMemory(image, @as([*c]const u8, @ptrCast(fileType)), @as([*c]c_int, @ptrCast(fileSize)))[0..@as(usize, @intCast(fileSize.*))];
pub fn exportImageToMemory(image: Image, fileType: []const u8) RaylibError![]u8 {
var _len: i32 = 0;
const _ptr = cdef.ExportImageToMemory(image, @as([*c]const u8, @ptrCast(fileType)), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.ExportImageToMemory;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Export image as code file defining an array of bytes, returns true on success
@ -4036,6 +3985,14 @@ pub fn imageColorReplace(image: *Image, color: Color, replace: Color) void {
cdef.ImageColorReplace(@as([*c]Image, @ptrCast(image)), color, replace);
}
/// Load colors palette from image as a Color array (RGBA - 32bit)
pub fn loadImagePalette(image: Image, maxPaletteSize: i32) RaylibError![]Color {
var _len: i32 = 0;
const _ptr = cdef.LoadImagePalette(image, @as(c_int, maxPaletteSize), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.LoadImagePalette;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Unload color data loaded with LoadImageColors()
pub fn unloadImageColors(colors: []Color) void {
cdef.UnloadImageColors(@as([*c]Color, @ptrCast(colors)));
@ -4396,6 +4353,14 @@ pub fn unloadUTF8(text: [:0]u8) void {
cdef.UnloadUTF8(@as([*c]u8, @ptrCast(text)));
}
/// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
pub fn loadCodepoints(text: []const u8) RaylibError![]i32 {
var _len: i32 = 0;
const _ptr = cdef.LoadCodepoints(@as([*c]const u8, @ptrCast(text)), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.LoadCodepoints;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Unload codepoints data from memory
pub fn unloadCodepoints(codepoints: []i32) void {
cdef.UnloadCodepoints(@as([*c]c_int, @ptrCast(codepoints)));
@ -4456,6 +4421,14 @@ pub fn textInsert(text: [:0]const u8, insert: [:0]const u8, position: i32) [:0]u
return std.mem.span(cdef.TextInsert(@as([*c]const u8, @ptrCast(text)), @as([*c]const u8, @ptrCast(insert)), @as(c_int, position)));
}
/// Split text into multiple strings
pub fn textSplit(text: []const u8, delimiter: u8) RaylibError![][:0]u8 {
var _len: i32 = 0;
const _ptr = cdef.TextSplit(@as([*c]const u8, @ptrCast(text)), delimiter, @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.TextSplit;
return @as([*][:0]u8, @ptrCast(_ptr))[0..@as(usize, @intCast(_len))];
}
/// Append text at specific position and move cursor!
pub fn textAppend(text: [:0]u8, append: [:0]const u8, position: *i32) void {
cdef.TextAppend(@as([*c]u8, @ptrCast(text)), @as([*c]const u8, @ptrCast(append)), @as([*c]c_int, @ptrCast(position)));
@ -4781,6 +4754,14 @@ pub fn setModelMeshMaterial(model: *Model, meshId: i32, materialId: i32) void {
cdef.SetModelMeshMaterial(@as([*c]Model, @ptrCast(model)), @as(c_int, meshId), @as(c_int, materialId));
}
/// Load model animations from file
pub fn loadModelAnimations(fileName: []const u8) RaylibError![]ModelAnimation {
var _len: i32 = 0;
const _ptr = cdef.LoadModelAnimations(@as([*c]const u8, @ptrCast(fileName)), @as([*c]c_int, @ptrCast(&_len)));
if (_ptr == 0) return RaylibError.LoadModelAnimations;
return _ptr[0..@as(usize, @intCast(_len))];
}
/// Update model animation pose (CPU)
pub fn updateModelAnimation(model: Model, anim: ModelAnimation, frame: i32) void {
cdef.UpdateModelAnimation(model, anim, @as(c_int, frame));

View File

@ -714,6 +714,11 @@ pub fn rlGetShaderIdDefault() u32 {
return @as(u32, cdef.rlGetShaderIdDefault());
}
/// Get default shader locations
pub fn rlGetShaderLocsDefault() [*c]c_int {
return cdef.rlGetShaderLocsDefault();
}
/// Load a render batch system
pub fn rlLoadRenderBatch(numBuffers: i32, bufferElements: i32) rlRenderBatch {
return cdef.rlLoadRenderBatch(@as(c_int, numBuffers), @as(c_int, bufferElements));