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" "c_uint": "u32"
} }
IGNORE_TYPES = [ IGNORE_C_TYPE = [
"[*c]Color", "rlGetShaderLocsDefault",
"[*c]GlyphInfo",
"[*c]c_int",
"[*c]c_uint",
"[*c][*c]u8",
"[*c][*c]const u8",
"[*c]Material",
"[*c]ModelAnimation",
"[*c]f32",
] ]
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 # 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. # knows that so we tell it to get the system specific size for us.
def c_to_zig_type(c: str) -> str: def c_to_zig_type(c: str) -> str:
@ -47,7 +123,9 @@ def c_to_zig_type(c: str) -> str:
return const + c 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"] NO_STRINGS = ["data", "fileData", "compData"]
single = [ single = [
@ -65,7 +143,7 @@ def ziggify_type(name: str, t: str, func_name) -> str:
"data", "compData", "points", "fileData", "colors", "pixels", "data", "compData", "points", "fileData", "colors", "pixels",
"fontChars", "chars", "recs", "codepoints", "textList", "transforms", "fontChars", "chars", "recs", "codepoints", "textList", "transforms",
"animations", "samples", "LoadImageColors", "LoadImagePalette", "animations", "samples", "LoadImageColors", "LoadImagePalette",
"LoadFontData", "LoadCodepoints", "TextSplit", "LoadMaterials", "LoadFontData", "LoadCodepoints", "LoadMaterials",
"LoadModelAnimations", "LoadWaveSamples", "images", "LoadModelAnimations", "LoadWaveSamples", "images",
"LoadRandomSequence", "sequence", "kernel", "GlyphInfo", "glyphs", "glyphRecs", "LoadRandomSequence", "sequence", "kernel", "GlyphInfo", "glyphs", "glyphRecs",
"matf", "rlGetShaderLocsDefault", "locs", "GuiGetIcons", "GuiLoadIcons" "matf", "rlGetShaderLocsDefault", "locs", "GuiGetIcons", "GuiLoadIcons"
@ -76,7 +154,7 @@ def ziggify_type(name: str, t: str, func_name) -> str:
return "[][:0]const u8" return "[][:0]const u8"
if t.startswith("[*c]") and name not in single and name not in multi: 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 string = True
else: else:
raise ValueError(f"{t} {name} not classified") raise ValueError(f"{t} {name} not classified")
@ -84,7 +162,9 @@ def ziggify_type(name: str, t: str, func_name) -> str:
pre = "" pre = ""
while t.startswith("[*c]"): while t.startswith("[*c]"):
t = t[4:] 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]" pre += "[:0]"
elif name in single: elif name in single:
pre += "*" pre += "*"
@ -94,7 +174,11 @@ def ziggify_type(name: str, t: str, func_name) -> str:
if t in ZIGGIFY: if t in ZIGGIFY:
t = ZIGGIFY[t] 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: def add_namespace_to_type(t: str) -> str:
@ -119,23 +203,20 @@ def add_namespace_to_type(t: str) -> str:
return pre + t return pre + t
def make_return_cast(source_type: str, dest_type: str, inner: str) -> str: def make_return_cast(func_name: str, source_type: str, dest_type: str, inner: str) -> str:
if source_type == dest_type: if source_type == dest_type or func_name in IGNORE_C_TYPE:
return inner return inner
if "ExportImageToMemory" in inner: if source_type.startswith("[*c][*c]"):
return f"{inner}[0..@as(usize, @intCast(fileSize.*))]" 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"]: if source_type in ["[*c]const u8", "[*c]u8"]:
return f"std.mem.span({inner})" return f"std.mem.span({inner})"
if source_type in ZIGGIFY: if source_type in ZIGGIFY:
return f"@as({dest_type}, {inner})" return f"@as({dest_type}, {inner})"
# These all have to be done manually because their sizes depend on the raise ValueError(f"Don't know what to do with '{func_name}': {source_type} {dest_type} {inner}")
# 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}")
def fix_pointer(name: str, t: str): 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) 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_arguments = ", ".join(zig_arguments)
zig_call_args = ", ".join(zig_call_args) zig_call_args = ", ".join(zig_call_args)
manual = [ if func_name in MANUAL or "FromMemory" in func_name:
"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:
continue 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) 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: if return_cast:
zig_funcs.append( zig_funcs.append(
inline_comment + inline_comment +
f"pub fn {zig_name}({zig_arguments}) {zig_return}" + f"pub fn {zig_name}({zig_arguments}) {zig_return}" +
" {\n " + " {\n " +
func_prelude +
("return " if zig_return != "void" else "") + ("return " if zig_return != "void" else "") +
return_cast + ";" return_cast + ";"
"\n}" "\n}"

View File

@ -14,11 +14,17 @@ test {
pub const RaylibError = error{ pub const RaylibError = error{
LoadFileData, LoadFileData,
CompressData,
DecompressData,
EncodeDataBase64,
DecodeDataBase64,
ExportImageToMemory,
LoadImageColors, LoadImageColors,
LoadImagePalette, LoadImagePalette,
LoadFont, LoadFont,
LoadFontData, LoadFontData,
LoadCodepoints, LoadCodepoints,
TextSplit,
LoadMaterial, LoadMaterial,
LoadMaterials, LoadMaterials,
LoadModelAnimations, LoadModelAnimations,
@ -2032,19 +2038,6 @@ pub fn loadRandomSequence(count: u32, min: i32, max: i32) []i32 {
return res; 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 /// Save data to file from byte array (write), returns true on success
pub fn saveFileData(fileName: [:0]const u8, data: []u8) bool { 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))); 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))); 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 { pub fn computeCRC32(data: []u8) u32 {
return cdef.ComputeCRC32(@as([*c]u8, @ptrCast(data)), @as(c_int, @intCast(data.len))); 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; 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) /// Load texture from file into GPU memory (VRAM)
pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D { pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D {
const texture = cdef.LoadTexture(@as([*c]const u8, @ptrCast(fileName))); 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; 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) /// Text formatting with variables (sprintf() style)
pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 { pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 {
comptime { 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); @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 /// Draw multiple mesh instances with material and different transforms
pub fn drawMeshInstanced(mesh: Mesh, material: Material, transforms: []const Matrix) void { 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))); 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; 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 /// Unload animation data
pub fn unloadModelAnimations(animations: []ModelAnimation) void { pub fn unloadModelAnimations(animations: []ModelAnimation) void {
cdef.UnloadModelAnimations(@as([*c]ModelAnimation, @ptrCast(animations)), @as(c_int, @intCast(animations.len))); cdef.UnloadModelAnimations(@as([*c]ModelAnimation, @ptrCast(animations)), @as(c_int, @intCast(animations.len)));

View File

@ -14,11 +14,17 @@ test {
pub const RaylibError = error{ pub const RaylibError = error{
LoadFileData, LoadFileData,
CompressData,
DecompressData,
EncodeDataBase64,
DecodeDataBase64,
ExportImageToMemory,
LoadImageColors, LoadImageColors,
LoadImagePalette, LoadImagePalette,
LoadFont, LoadFont,
LoadFontData, LoadFontData,
LoadCodepoints, LoadCodepoints,
TextSplit,
LoadMaterial, LoadMaterial,
LoadMaterials, LoadMaterials,
LoadModelAnimations, LoadModelAnimations,
@ -2032,19 +2038,6 @@ pub fn loadRandomSequence(count: u32, min: i32, max: i32) []i32 {
return res; 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 /// Save data to file from byte array (write), returns true on success
pub fn saveFileData(fileName: [:0]const u8, data: []u8) bool { 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))); 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))); 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 { pub fn computeCRC32(data: []u8) u32 {
return cdef.ComputeCRC32(@as([*c]u8, @ptrCast(data)), @as(c_int, @intCast(data.len))); 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; 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) /// Load texture from file into GPU memory (VRAM)
pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D { pub fn loadTexture(fileName: [:0]const u8) RaylibError!Texture2D {
const texture = cdef.LoadTexture(@as([*c]const u8, @ptrCast(fileName))); 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; 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) /// Text formatting with variables (sprintf() style)
pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 { pub fn textFormat(text: [:0]const u8, args: anytype) [:0]const u8 {
comptime { 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); @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 /// Draw multiple mesh instances with material and different transforms
pub fn drawMeshInstanced(mesh: Mesh, material: Material, transforms: []const Matrix) void { 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))); 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; 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 /// Unload animation data
pub fn unloadModelAnimations(animations: []ModelAnimation) void { pub fn unloadModelAnimations(animations: []ModelAnimation) void {
cdef.UnloadModelAnimations(@as([*c]ModelAnimation, @ptrCast(animations)), @as(c_int, @intCast(animations.len))); 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); 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() /// Unload file data allocated by LoadFileData()
pub fn unloadFileData(data: []u8) void { pub fn unloadFileData(data: []u8) void {
cdef.UnloadFileData(@as([*c]u8, @ptrCast(data))); 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)))); 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 /// Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
pub fn loadAutomationEventList(fileName: [:0]const u8) AutomationEventList { pub fn loadAutomationEventList(fileName: [:0]const u8) AutomationEventList {
return cdef.LoadAutomationEventList(@as([*c]const u8, @ptrCast(fileName))); 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 /// Export image to memory buffer
pub fn exportImageToMemory(image: Image, fileType: [:0]const u8, fileSize: *i32) [:0]u8 { pub fn exportImageToMemory(image: Image, fileType: []const u8) RaylibError![]u8 {
return cdef.ExportImageToMemory(image, @as([*c]const u8, @ptrCast(fileType)), @as([*c]c_int, @ptrCast(fileSize)))[0..@as(usize, @intCast(fileSize.*))]; 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 /// 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); 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() /// Unload color data loaded with LoadImageColors()
pub fn unloadImageColors(colors: []Color) void { pub fn unloadImageColors(colors: []Color) void {
cdef.UnloadImageColors(@as([*c]Color, @ptrCast(colors))); 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))); 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 /// Unload codepoints data from memory
pub fn unloadCodepoints(codepoints: []i32) void { pub fn unloadCodepoints(codepoints: []i32) void {
cdef.UnloadCodepoints(@as([*c]c_int, @ptrCast(codepoints))); 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))); 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! /// Append text at specific position and move cursor!
pub fn textAppend(text: [:0]u8, append: [:0]const u8, position: *i32) void { 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))); 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)); 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) /// Update model animation pose (CPU)
pub fn updateModelAnimation(model: Model, anim: ModelAnimation, frame: i32) void { pub fn updateModelAnimation(model: Model, anim: ModelAnimation, frame: i32) void {
cdef.UpdateModelAnimation(model, anim, @as(c_int, frame)); cdef.UpdateModelAnimation(model, anim, @as(c_int, frame));

View File

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