Merge branch 'master' of https://github.com/raysan5/raylib into pure

This commit is contained in:
ColleagueRiley 2024-10-21 16:21:15 -04:00
commit fc96f333a4
39 changed files with 1910 additions and 5842 deletions

View File

@ -31,7 +31,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.0** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |

437
build.zig
View File

@ -1,11 +1,434 @@
const std = @import("std");
const raylib = @import("src/build.zig");
const builtin = @import("builtin");
// This has been tested to work with zig 0.12.0
pub fn build(b: *std.Build) !void {
try raylib.build(b);
/// Minimum supported version of Zig
const min_ver = "0.12.0";
comptime {
const order = std.SemanticVersion.order;
const parse = std.SemanticVersion.parse;
if (order(builtin.zig_version, parse(min_ver) catch unreachable) == .lt)
@compileError("Raylib requires zig version " ++ min_ver);
}
// expose helper functions to user's build.zig
pub const addRaylib = raylib.addRaylib;
pub const addRaygui = raylib.addRaygui;
// NOTE(freakmangd): I don't like using a global here, but it prevents having to
// get the flags a second time when adding raygui
var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{};
// This has been tested with zig version 0.12.0
pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
const raylib_dep = b.dependencyFromBuildZig(@This(), .{
.target = target,
.optimize = optimize,
.raudio = options.raudio,
.rmodels = options.rmodels,
.rshapes = options.rshapes,
.rtext = options.rtext,
.rtextures = options.rtextures,
.platform = options.platform,
.shared = options.shared,
.linux_display_backend = options.linux_display_backend,
.opengl_version = options.opengl_version,
.config = options.config,
});
const raylib = raylib_dep.artifact("raylib");
if (options.raygui) {
const raygui_dep = b.dependency(options.raygui_dependency_name, .{});
addRaygui(b, raylib, raygui_dep);
}
return raylib;
}
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
raylib.defineCMacro("PLATFORM_DESKTOP", null);
switch (platform) {
.glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null),
.rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null),
.sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null),
else => {},
}
}
/// A list of all flags from `src/config.h` that one may override
const config_h_flags = outer: {
// Set this value higher if compile errors happen as `src/config.h` gets larger
@setEvalBranchQuota(1 << 20);
const config_h = @embedFile("src/config.h");
var flags: [std.mem.count(u8, config_h, "\n") + 1][]const u8 = undefined;
var i = 0;
var lines = std.mem.tokenizeScalar(u8, config_h, '\n');
while (lines.next()) |line| {
if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
if (std.mem.startsWith(u8, line, "//")) continue;
if (std.mem.startsWith(u8, line, "#if")) continue;
var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
flag = flag["#define ".len - 1 ..]; // Remove #define
flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
flag = "-D" ++ flag; // Prepend with -D
flags[i] = flag;
i += 1;
}
// Uncomment this to check what flags normally get passed
//@compileLog(flags[0..i].*);
break :outer flags[0..i].*;
};
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
raylib_flags_arr.clearRetainingCapacity();
const shared_flags = &[_][]const u8{
"-fPIC",
"-DBUILD_LIBTYPE_SHARED",
};
try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{
"-std=gnu99",
"-D_GNU_SOURCE",
"-DGL_SILENCE_DEPRECATION=199309L",
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
});
if (options.config.len > 0) {
// Sets a flag indiciating the use of a custom `config.h`
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
// Splits a space-separated list of config flags into multiple flags
//
// Note: This means certain flags like `-x c++` won't be processed properly.
// `-xc++` or similar should be used when possible
var config_iter = std.mem.tokenizeScalar(u8, options.config, ' ');
// Apply config flags supplied by the user
while (config_iter.next()) |config_flag|
try raylib_flags_arr.append(b.allocator, config_flag);
// Apply all relevant configs from `src/config.h` *except* the user-specified ones
//
// Note: Currently using a suboptimal `O(m*n)` time algorithm where:
// `m` corresponds roughly to the number of lines in `src/config.h`
// `n` corresponds to the number of user-specified flags
outer: for (config_h_flags) |flag| {
// If a user already specified the flag, skip it
while (config_iter.next()) |config_flag| {
// For a user-specified flag to match, it must share the same prefix and have the
// same length or be followed by an equals sign
if (!std.mem.startsWith(u8, config_flag, flag)) continue;
if (config_flag.len == flag.len or config_flag[flag.len] == '=') continue :outer;
}
// Otherwise, append default value from config.h to compile flags
try raylib_flags_arr.append(b.allocator, flag);
}
}
if (options.shared) {
try raylib_flags_arr.appendSlice(b.allocator, shared_flags);
}
const raylib = if (options.shared)
b.addSharedLibrary(.{
.name = "raylib",
.target = target,
.optimize = optimize,
})
else
b.addStaticLibrary(.{
.name = "raylib",
.target = target,
.optimize = optimize,
});
raylib.linkLibC();
// No GLFW required on PLATFORM_DRM
if (options.platform != .drm) {
raylib.addIncludePath(b.path("src/external/glfw/include"));
}
var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" });
if (options.raudio) {
try c_source_files.append("src/raudio.c");
}
if (options.rmodels) {
try c_source_files.append("src/rmodels.c");
}
if (options.rshapes) {
try c_source_files.append("src/rshapes.c");
}
if (options.rtext) {
try c_source_files.append("src/rtext.c");
}
if (options.rtextures) {
try c_source_files.append("src/rtextures.c");
}
if (options.opengl_version != .auto) {
raylib.defineCMacro(options.opengl_version.toCMacroStr(), null);
}
switch (target.result.os.tag) {
.windows => {
try c_source_files.append("src/rglfw.c");
raylib.linkSystemLibrary("winmm");
raylib.linkSystemLibrary("gdi32");
raylib.linkSystemLibrary("opengl32");
setDesktopPlatform(raylib, options.platform);
},
.linux => {
if (options.platform != .drm) {
try c_source_files.append("src/rglfw.c");
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
raylib.addIncludePath(.{ .cwd_relative = "/usr/include" });
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib.defineCMacro("_GLFW_X11", null);
raylib.linkSystemLibrary("X11");
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("`wayland-scanner` not found");
};
raylib.defineCMacro("_GLFW_WAYLAND", null);
raylib.linkSystemLibrary("wayland-client");
raylib.linkSystemLibrary("wayland-cursor");
raylib.linkSystemLibrary("wayland-egl");
raylib.linkSystemLibrary("xkbcommon");
waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
}
setDesktopPlatform(raylib, options.platform);
} else {
if (options.opengl_version == .auto) {
raylib.linkSystemLibrary("GLESv2");
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
}
raylib.linkSystemLibrary("EGL");
raylib.linkSystemLibrary("drm");
raylib.linkSystemLibrary("gbm");
raylib.linkSystemLibrary("pthread");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("dl");
raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" });
raylib.defineCMacro("PLATFORM_DRM", null);
raylib.defineCMacro("EGL_NO_X11", null);
raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048");
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
try c_source_files.append("rglfw.c");
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
raylib.linkSystemLibrary("Xrandr");
raylib.linkSystemLibrary("Xinerama");
raylib.linkSystemLibrary("Xi");
raylib.linkSystemLibrary("Xxf86vm");
raylib.linkSystemLibrary("Xcursor");
setDesktopPlatform(raylib, options.platform);
},
.macos => {
// On macos rglfw.c include Objective-C files.
try raylib_flags_arr.append(b.allocator, "-ObjC");
raylib.root_module.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
raylib.linkFramework("Foundation");
raylib.linkFramework("CoreServices");
raylib.linkFramework("CoreGraphics");
raylib.linkFramework("AppKit");
raylib.linkFramework("IOKit");
setDesktopPlatform(raylib, options.platform);
},
.emscripten => {
raylib.defineCMacro("PLATFORM_WEB", null);
if (options.opengl_version == .auto) {
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
}
if (b.sysroot == null) {
@panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'");
}
const cache_include = b.pathJoin(&.{ b.sysroot.?, "cache", "sysroot", "include" });
var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
dir.close();
raylib.addIncludePath(.{ .cwd_relative = cache_include });
},
else => {
@panic("Unsupported OS");
},
}
raylib.root_module.addCSourceFiles(.{
.files = c_source_files.items,
.flags = raylib_flags_arr.items,
});
return raylib;
}
/// This function does not need to be called if you passed .raygui = true to addRaylib
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void {
if (raylib_flags_arr.items.len == 0) {
@panic(
\\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib")
);
}
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items });
raylib.addIncludePath(raygui_dep.path("src"));
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
}
pub const Options = struct {
raudio: bool = true,
rmodels: bool = true,
rshapes: bool = true,
rtext: bool = true,
rtextures: bool = true,
raygui: bool = false,
platform: PlatformBackend = .glfw,
shared: bool = false,
linux_display_backend: LinuxDisplayBackend = .Both,
opengl_version: OpenglVersion = .auto,
/// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
config: []const u8 = &.{},
raygui_dependency_name: []const u8 = "raygui",
const defaults = Options{};
fn getOptions(b: *std.Build) Options {
return .{
.platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform,
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
.raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui,
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
.shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
.config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{},
};
}
};
pub const OpenglVersion = enum {
auto,
gl_1_1,
gl_2_1,
gl_3_3,
gl_4_3,
gles_2,
gles_3,
pub fn toCMacroStr(self: @This()) []const u8 {
switch (self) {
.auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
.gl_1_1 => return "GRAPHICS_API_OPENGL_11",
.gl_2_1 => return "GRAPHICS_API_OPENGL_21",
.gl_3_3 => return "GRAPHICS_API_OPENGL_33",
.gl_4_3 => return "GRAPHICS_API_OPENGL_43",
.gles_2 => return "GRAPHICS_API_OPENGL_ES2",
.gles_3 => return "GRAPHICS_API_OPENGL_ES3",
}
}
};
pub const LinuxDisplayBackend = enum {
X11,
Wayland,
Both,
};
pub const PlatformBackend = enum {
glfw,
rgfw,
sdl,
drm,
};
pub fn build(b: *std.Build) !void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const lib = try compileRaylib(b, target, optimize, Options.getOptions(b));
lib.installHeader(b.path("src/raylib.h"), "raylib.h");
lib.installHeader(b.path("src/raymath.h"), "raymath.h");
lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
b.installArtifact(lib);
}
fn waylandGenerate(
b: *std.Build,
raylib: *std.Build.Step.Compile,
comptime protocol: []const u8,
comptime basename: []const u8,
) void {
const waylandDir = "src/external/glfw/deps/wayland";
const protocolDir = b.pathJoin(&.{ waylandDir, protocol });
const clientHeader = basename ++ ".h";
const privateCode = basename ++ "-code.h";
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
client_step.addFileArg(b.path(protocolDir));
raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
private_step.addFileArg(b.path(protocolDir));
raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname());
raylib.step.dependOn(&client_step.step);
raylib.step.dependOn(&private_step.step);
}

View File

@ -549,7 +549,6 @@ TEXTURES = \
textures/textures_sprite_button \
textures/textures_sprite_explosion \
textures/textures_srcrec_dstrec \
textures/textures_svg_loading \
textures/textures_textured_curve \
textures/textures_to_image

View File

@ -415,7 +415,6 @@ TEXTURES = \
textures/textures_sprite_button \
textures/textures_sprite_explosion \
textures/textures_srcrec_dstrec \
textures/textures_svg_loading \
textures/textures_textured_curve \
textures/textures_to_image
@ -776,10 +775,6 @@ textures/textures_srcrec_dstrec: textures/textures_srcrec_dstrec.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/scarfy.png@resources/scarfy.png
textures/textures_svg_loading: textures/textures_svg_loading.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/test.svg
textures/textures_textured_curve: textures/textures_textured_curve.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/road.png@resources/road.png

View File

@ -81,7 +81,6 @@ int main(void)
// Update model animation
ModelAnimation anim = modelAnimations[animIndex];
animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount;
UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -1,72 +0,0 @@
/*******************************************************************************************
*
* raylib [textures] example - SVG loading and texture creation
*
* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
*
* Example originally created with raylib 4.2, last time updated with raylib 4.2
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2022 Dennis Meinen (@bixxy#4258 on Discord)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading");
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Image image = LoadImageSvg("resources/test.svg", 400, 350); // Loaded in CPU memory (RAM)
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE);
//Red border to illustrate how the SVG is centered within the specified dimensions
DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED);
DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Texture unloading
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -3763,8 +3763,8 @@
]
},
{
"name": "IsShaderReady",
"description": "Check if a shader is ready",
"name": "IsShaderValid",
"description": "Check if a shader is valid (loaded on GPU)",
"returnType": "bool",
"params": [
{
@ -4691,6 +4691,51 @@
}
]
},
{
"name": "ComputeCRC32",
"description": "Compute CRC32 hash code",
"returnType": "unsigned int",
"params": [
{
"type": "unsigned char *",
"name": "data"
},
{
"type": "int",
"name": "dataSize"
}
]
},
{
"name": "ComputeMD5",
"description": "Compute MD5 hash code, returns static int[4] (16 bytes)",
"returnType": "unsigned int *",
"params": [
{
"type": "unsigned char *",
"name": "data"
},
{
"type": "int",
"name": "dataSize"
}
]
},
{
"name": "ComputeSHA1",
"description": "Compute SHA1 hash code, returns static int[5] (20 bytes)",
"returnType": "unsigned int *",
"params": [
{
"type": "unsigned char *",
"name": "data"
},
{
"type": "int",
"name": "dataSize"
}
]
},
{
"name": "LoadAutomationEventList",
"description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@ -5186,7 +5231,7 @@
},
{
"name": "GetGestureHoldDuration",
"description": "Get gesture hold time in milliseconds",
"description": "Get gesture hold time in seconds",
"returnType": "float"
},
{
@ -6815,25 +6860,6 @@
}
]
},
{
"name": "LoadImageSvg",
"description": "Load image from SVG file data or string with specified size",
"returnType": "Image",
"params": [
{
"type": "const char *",
"name": "fileNameOrString"
},
{
"type": "int",
"name": "width"
},
{
"type": "int",
"name": "height"
}
]
},
{
"name": "LoadImageAnim",
"description": "Load image sequence from file (frames appended to image.data)",
@ -6908,8 +6934,8 @@
"returnType": "Image"
},
{
"name": "IsImageReady",
"description": "Check if an image is ready",
"name": "IsImageValid",
"description": "Check if an image is valid (data and parameters)",
"returnType": "bool",
"params": [
{
@ -8372,8 +8398,8 @@
]
},
{
"name": "IsTextureReady",
"description": "Check if a texture is ready",
"name": "IsTextureValid",
"description": "Check if a texture is valid (loaded in GPU)",
"returnType": "bool",
"params": [
{
@ -8394,8 +8420,8 @@
]
},
{
"name": "IsRenderTextureReady",
"description": "Check if a render texture is ready",
"name": "IsRenderTextureValid",
"description": "Check if a render texture is valid (loaded in GPU)",
"returnType": "bool",
"params": [
{
@ -8989,8 +9015,8 @@
]
},
{
"name": "IsFontReady",
"description": "Check if a font is ready",
"name": "IsFontValid",
"description": "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
"returnType": "bool",
"params": [
{
@ -10281,8 +10307,8 @@
]
},
{
"name": "IsModelReady",
"description": "Check if a model is ready",
"name": "IsModelValid",
"description": "Check if a model is valid (loaded in GPU, VAO/VBOs)",
"returnType": "bool",
"params": [
{
@ -10968,8 +10994,8 @@
"returnType": "Material"
},
{
"name": "IsMaterialReady",
"description": "Check if a material is ready",
"name": "IsMaterialValid",
"description": "Check if a material is valid (shader assigned, map textures loaded in GPU)",
"returnType": "bool",
"params": [
{
@ -11343,8 +11369,8 @@
]
},
{
"name": "IsWaveReady",
"description": "Checks if wave data is ready",
"name": "IsWaveValid",
"description": "Checks if wave data is valid (data loaded and parameters)",
"returnType": "bool",
"params": [
{
@ -11387,8 +11413,8 @@
]
},
{
"name": "IsSoundReady",
"description": "Checks if a sound is ready",
"name": "IsSoundValid",
"description": "Checks if a sound is valid (data loaded and buffers initialized)",
"returnType": "bool",
"params": [
{
@ -11685,8 +11711,8 @@
]
},
{
"name": "IsMusicReady",
"description": "Checks if a music stream is ready",
"name": "IsMusicValid",
"description": "Checks if a music stream is valid (context and buffers initialized)",
"returnType": "bool",
"params": [
{
@ -11874,8 +11900,8 @@
]
},
{
"name": "IsAudioStreamReady",
"description": "Checks if an audio stream is ready",
"name": "IsAudioStreamValid",
"description": "Checks if an audio stream is valid (buffers initialized)",
"returnType": "bool",
"params": [
{

View File

@ -3589,8 +3589,8 @@ return {
}
},
{
name = "IsShaderReady",
description = "Check if a shader is ready",
name = "IsShaderValid",
description = "Check if a shader is valid (loaded on GPU)",
returnType = "bool",
params = {
{type = "Shader", name = "shader"}
@ -4190,6 +4190,33 @@ return {
{type = "int *", name = "outputSize"}
}
},
{
name = "ComputeCRC32",
description = "Compute CRC32 hash code",
returnType = "unsigned int",
params = {
{type = "unsigned char *", name = "data"},
{type = "int", name = "dataSize"}
}
},
{
name = "ComputeMD5",
description = "Compute MD5 hash code, returns static int[4] (16 bytes)",
returnType = "unsigned int *",
params = {
{type = "unsigned char *", name = "data"},
{type = "int", name = "dataSize"}
}
},
{
name = "ComputeSHA1",
description = "Compute SHA1 hash code, returns static int[5] (20 bytes)",
returnType = "unsigned int *",
params = {
{type = "unsigned char *", name = "data"},
{type = "int", name = "dataSize"}
}
},
{
name = "LoadAutomationEventList",
description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@ -4550,7 +4577,7 @@ return {
},
{
name = "GetGestureHoldDuration",
description = "Get gesture hold time in milliseconds",
description = "Get gesture hold time in seconds",
returnType = "float"
},
{
@ -5339,16 +5366,6 @@ return {
{type = "int", name = "headerSize"}
}
},
{
name = "LoadImageSvg",
description = "Load image from SVG file data or string with specified size",
returnType = "Image",
params = {
{type = "const char *", name = "fileNameOrString"},
{type = "int", name = "width"},
{type = "int", name = "height"}
}
},
{
name = "LoadImageAnim",
description = "Load image sequence from file (frames appended to image.data)",
@ -5393,8 +5410,8 @@ return {
returnType = "Image"
},
{
name = "IsImageReady",
description = "Check if an image is ready",
name = "IsImageValid",
description = "Check if an image is valid (data and parameters)",
returnType = "bool",
params = {
{type = "Image", name = "image"}
@ -6158,8 +6175,8 @@ return {
}
},
{
name = "IsTextureReady",
description = "Check if a texture is ready",
name = "IsTextureValid",
description = "Check if a texture is valid (loaded in GPU)",
returnType = "bool",
params = {
{type = "Texture2D", name = "texture"}
@ -6174,8 +6191,8 @@ return {
}
},
{
name = "IsRenderTextureReady",
description = "Check if a render texture is ready",
name = "IsRenderTextureValid",
description = "Check if a render texture is valid (loaded in GPU)",
returnType = "bool",
params = {
{type = "RenderTexture2D", name = "target"}
@ -6505,8 +6522,8 @@ return {
}
},
{
name = "IsFontReady",
description = "Check if a font is ready",
name = "IsFontValid",
description = "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
returnType = "bool",
params = {
{type = "Font", name = "font"}
@ -7185,8 +7202,8 @@ return {
}
},
{
name = "IsModelReady",
description = "Check if a model is ready",
name = "IsModelValid",
description = "Check if a model is valid (loaded in GPU, VAO/VBOs)",
returnType = "bool",
params = {
{type = "Model", name = "model"}
@ -7539,8 +7556,8 @@ return {
returnType = "Material"
},
{
name = "IsMaterialReady",
description = "Check if a material is ready",
name = "IsMaterialValid",
description = "Check if a material is valid (shader assigned, map textures loaded in GPU)",
returnType = "bool",
params = {
{type = "Material", name = "material"}
@ -7758,8 +7775,8 @@ return {
}
},
{
name = "IsWaveReady",
description = "Checks if wave data is ready",
name = "IsWaveValid",
description = "Checks if wave data is valid (data loaded and parameters)",
returnType = "bool",
params = {
{type = "Wave", name = "wave"}
@ -7790,8 +7807,8 @@ return {
}
},
{
name = "IsSoundReady",
description = "Checks if a sound is ready",
name = "IsSoundValid",
description = "Checks if a sound is valid (data loaded and buffers initialized)",
returnType = "bool",
params = {
{type = "Sound", name = "sound"}
@ -7980,8 +7997,8 @@ return {
}
},
{
name = "IsMusicReady",
description = "Checks if a music stream is ready",
name = "IsMusicValid",
description = "Checks if a music stream is valid (context and buffers initialized)",
returnType = "bool",
params = {
{type = "Music", name = "music"}
@ -8106,8 +8123,8 @@ return {
}
},
{
name = "IsAudioStreamReady",
description = "Checks if an audio stream is ready",
name = "IsAudioStreamValid",
description = "Checks if an audio stream is valid (buffers initialized)",
returnType = "bool",
params = {
{type = "AudioStream", name = "stream"}

File diff suppressed because it is too large Load Diff

View File

@ -675,7 +675,7 @@
<Param type="unsigned int" name="frames" desc="" />
</Callback>
</Callbacks>
<Functions count="578">
<Functions count="580">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" />
@ -871,7 +871,7 @@
<Param type="const char *" name="vsCode" desc="" />
<Param type="const char *" name="fsCode" desc="" />
</Function>
<Function name="IsShaderReady" retType="bool" paramCount="1" desc="Check if a shader is ready">
<Function name="IsShaderValid" retType="bool" paramCount="1" desc="Check if a shader is valid (loaded on GPU)">
<Param type="Shader" name="shader" desc="" />
</Function>
<Function name="GetShaderLocation" retType="int" paramCount="2" desc="Get shader uniform location">
@ -1126,6 +1126,18 @@
<Param type="const unsigned char *" name="data" desc="" />
<Param type="int *" name="outputSize" desc="" />
</Function>
<Function name="ComputeCRC32" retType="unsigned int" paramCount="2" desc="Compute CRC32 hash code">
<Param type="unsigned char *" name="data" desc="" />
<Param type="int" name="dataSize" desc="" />
</Function>
<Function name="ComputeMD5" retType="unsigned int *" paramCount="2" desc="Compute MD5 hash code, returns static int[4] (16 bytes)">
<Param type="unsigned char *" name="data" desc="" />
<Param type="int" name="dataSize" desc="" />
</Function>
<Function name="ComputeSHA1" retType="unsigned int *" paramCount="2" desc="Compute SHA1 hash code, returns static int[5] (20 bytes)">
<Param type="unsigned char *" name="data" desc="" />
<Param type="int" name="dataSize" desc="" />
</Function>
<Function name="LoadAutomationEventList" retType="AutomationEventList" paramCount="1" desc="Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS">
<Param type="const char *" name="fileName" desc="" />
</Function>
@ -1269,7 +1281,7 @@
</Function>
<Function name="GetGestureDetected" retType="int" paramCount="0" desc="Get latest detected gesture">
</Function>
<Function name="GetGestureHoldDuration" retType="float" paramCount="0" desc="Get gesture hold time in milliseconds">
<Function name="GetGestureHoldDuration" retType="float" paramCount="0" desc="Get gesture hold time in seconds">
</Function>
<Function name="GetGestureDragVector" retType="Vector2" paramCount="0" desc="Get gesture drag vector">
</Function>
@ -1699,11 +1711,6 @@
<Param type="int" name="format" desc="" />
<Param type="int" name="headerSize" desc="" />
</Function>
<Function name="LoadImageSvg" retType="Image" paramCount="3" desc="Load image from SVG file data or string with specified size">
<Param type="const char *" name="fileNameOrString" desc="" />
<Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" />
</Function>
<Function name="LoadImageAnim" retType="Image" paramCount="2" desc="Load image sequence from file (frames appended to image.data)">
<Param type="const char *" name="fileName" desc="" />
<Param type="int *" name="frames" desc="" />
@ -1724,7 +1731,7 @@
</Function>
<Function name="LoadImageFromScreen" retType="Image" paramCount="0" desc="Load image from screen buffer and (screenshot)">
</Function>
<Function name="IsImageReady" retType="bool" paramCount="1" desc="Check if an image is ready">
<Function name="IsImageValid" retType="bool" paramCount="1" desc="Check if an image is valid (data and parameters)">
<Param type="Image" name="image" desc="" />
</Function>
<Function name="UnloadImage" retType="void" paramCount="1" desc="Unload image from CPU memory (RAM)">
@ -2109,13 +2116,13 @@
<Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" />
</Function>
<Function name="IsTextureReady" retType="bool" paramCount="1" desc="Check if a texture is ready">
<Function name="IsTextureValid" retType="bool" paramCount="1" desc="Check if a texture is valid (loaded in GPU)">
<Param type="Texture2D" name="texture" desc="" />
</Function>
<Function name="UnloadTexture" retType="void" paramCount="1" desc="Unload texture from GPU memory (VRAM)">
<Param type="Texture2D" name="texture" desc="" />
</Function>
<Function name="IsRenderTextureReady" retType="bool" paramCount="1" desc="Check if a render texture is ready">
<Function name="IsRenderTextureValid" retType="bool" paramCount="1" desc="Check if a render texture is valid (loaded in GPU)">
<Param type="RenderTexture2D" name="target" desc="" />
</Function>
<Function name="UnloadRenderTexture" retType="void" paramCount="1" desc="Unload render texture from GPU memory (VRAM)">
@ -2273,7 +2280,7 @@
<Param type="int *" name="codepoints" desc="" />
<Param type="int" name="codepointCount" desc="" />
</Function>
<Function name="IsFontReady" retType="bool" paramCount="1" desc="Check if a font is ready">
<Function name="IsFontValid" retType="bool" paramCount="1" desc="Check if a font is valid (font data loaded, WARNING: GPU texture not checked)">
<Param type="Font" name="font" desc="" />
</Function>
<Function name="LoadFontData" retType="GlyphInfo *" paramCount="6" desc="Load font data for further use">
@ -2613,7 +2620,7 @@
<Function name="LoadModelFromMesh" retType="Model" paramCount="1" desc="Load model from generated mesh (default material)">
<Param type="Mesh" name="mesh" desc="" />
</Function>
<Function name="IsModelReady" retType="bool" paramCount="1" desc="Check if a model is ready">
<Function name="IsModelValid" retType="bool" paramCount="1" desc="Check if a model is valid (loaded in GPU, VAO/VBOs)">
<Param type="Model" name="model" desc="" />
</Function>
<Function name="UnloadModel" retType="void" paramCount="1" desc="Unload model (including meshes) from memory (RAM and/or VRAM)">
@ -2794,7 +2801,7 @@
</Function>
<Function name="LoadMaterialDefault" retType="Material" paramCount="0" desc="Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)">
</Function>
<Function name="IsMaterialReady" retType="bool" paramCount="1" desc="Check if a material is ready">
<Function name="IsMaterialValid" retType="bool" paramCount="1" desc="Check if a material is valid (shader assigned, map textures loaded in GPU)">
<Param type="Material" name="material" desc="" />
</Function>
<Function name="UnloadMaterial" retType="void" paramCount="1" desc="Unload material from GPU memory (VRAM)">
@ -2896,7 +2903,7 @@
<Param type="const unsigned char *" name="fileData" desc="" />
<Param type="int" name="dataSize" desc="" />
</Function>
<Function name="IsWaveReady" retType="bool" paramCount="1" desc="Checks if wave data is ready">
<Function name="IsWaveValid" retType="bool" paramCount="1" desc="Checks if wave data is valid (data loaded and parameters)">
<Param type="Wave" name="wave" desc="" />
</Function>
<Function name="LoadSound" retType="Sound" paramCount="1" desc="Load sound from file">
@ -2908,7 +2915,7 @@
<Function name="LoadSoundAlias" retType="Sound" paramCount="1" desc="Create a new sound that shares the same sample data as the source sound, does not own the sound data">
<Param type="Sound" name="source" desc="" />
</Function>
<Function name="IsSoundReady" retType="bool" paramCount="1" desc="Checks if a sound is ready">
<Function name="IsSoundValid" retType="bool" paramCount="1" desc="Checks if a sound is valid (data loaded and buffers initialized)">
<Param type="Sound" name="sound" desc="" />
</Function>
<Function name="UpdateSound" retType="void" paramCount="3" desc="Update sound buffer with new data">
@ -2988,7 +2995,7 @@
<Param type="const unsigned char *" name="data" desc="" />
<Param type="int" name="dataSize" desc="" />
</Function>
<Function name="IsMusicReady" retType="bool" paramCount="1" desc="Checks if a music stream is ready">
<Function name="IsMusicValid" retType="bool" paramCount="1" desc="Checks if a music stream is valid (context and buffers initialized)">
<Param type="Music" name="music" desc="" />
</Function>
<Function name="UnloadMusicStream" retType="void" paramCount="1" desc="Unload music stream">
@ -3039,7 +3046,7 @@
<Param type="unsigned int" name="sampleSize" desc="" />
<Param type="unsigned int" name="channels" desc="" />
</Function>
<Function name="IsAudioStreamReady" retType="bool" paramCount="1" desc="Checks if an audio stream is ready">
<Function name="IsAudioStreamValid" retType="bool" paramCount="1" desc="Checks if an audio stream is valid (buffers initialized)">
<Param type="AudioStream" name="stream" desc="" />
</Function>
<Function name="UnloadAudioStream" retType="void" paramCount="1" desc="Unload audio stream and free memory">

View File

@ -293,8 +293,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_outline", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_tiling", "examples\shaders_texture_tiling.vcxproj", "{EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "textures_svg_loading", "examples\textures_svg_loading.vcxproj", "{D8026C60-CCBC-45DF-9085-BF21569EB414}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_splines_drawing", "examples\shapes_splines_drawing.vcxproj", "{DF25E545-00FF-4E64-844C-7DF98991F901}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "examples\shapes_top_down_lights.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}"

View File

@ -352,9 +352,9 @@ SRC_DIR = src
OBJ_DIR = obj
# Define all object files from source files
SRC = $(call rwildcard, *.c, *.h)
SRC = $(call rwildcard, ./, *.c, *.h)
#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
OBJS ?= main.c
OBJS = $(patsubst %.c,%.o,$(filter %.c,$(SRC)))
# For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_ANDROID)

View File

@ -109,8 +109,9 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src
# Use external GLFW library instead of rglfw module
USE_EXTERNAL_GLFW ?= FALSE
# Enable support for both Wayland and X11 by default on Linux when using GLFW
GLFW_LINUX_ENABLE_WAYLAND ?= TRUE
# Enable support for X11 by default on Linux when using GLFW
# NOTE: Wayland is disabled by default, only enable if you are sure
GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
GLFW_LINUX_ENABLE_X11 ?= TRUE
# PLATFORM_DESKTOP_SDL: It requires SDL library to be provided externally

View File

@ -1,397 +0,0 @@
const std = @import("std");
const builtin = @import("builtin");
comptime {
if (builtin.zig_version.minor < 12) @compileError("Raylib requires zig version 0.12.0");
}
// NOTE(freakmangd): I don't like using a global here, but it prevents having to
// get the flags a second time when adding raygui
var raylib_flags_arr: std.ArrayListUnmanaged([]const u8) = .{};
/// we're not inside the actual build script recognized by the
/// zig build system; use this type where one would otherwise
/// use `@This()` when inside the actual entrypoint file.
const BuildScript = @import("../build.zig");
// This has been tested with zig version 0.12.0
pub fn addRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
const raylib_dep = b.dependencyFromBuildZig(BuildScript, .{
.target = target,
.optimize = optimize,
.raudio = options.raudio,
.rmodels = options.rmodels,
.rshapes = options.rshapes,
.rtext = options.rtext,
.rtextures = options.rtextures,
.platform_drm = options.platform_drm,
.shared = options.shared,
.linux_display_backend = options.linux_display_backend,
.opengl_version = options.opengl_version,
.config = options.config,
});
const raylib = raylib_dep.artifact("raylib");
if (options.raygui) {
const raygui_dep = b.dependency(options.raygui_dependency_name, .{});
addRaygui(b, raylib, raygui_dep);
}
return raylib;
}
fn setDesktopPlatform(raylib: *std.Build.Step.Compile, platform: PlatformBackend) void {
raylib.defineCMacro("PLATFORM_DESKTOP", null);
switch (platform) {
.glfw => raylib.defineCMacro("PLATFORM_DESKTOP_GLFW", null),
.rgfw => raylib.defineCMacro("PLATFORM_DESKTOP_RGFW", null),
.sdl => raylib.defineCMacro("PLATFORM_DESKTOP_SDL", null),
else => {},
}
}
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
raylib_flags_arr.clearRetainingCapacity();
const shared_flags = &[_][]const u8{
"-fPIC",
"-DBUILD_LIBTYPE_SHARED",
};
try raylib_flags_arr.appendSlice(b.allocator, &[_][]const u8{
"-std=gnu99",
"-D_GNU_SOURCE",
"-DGL_SILENCE_DEPRECATION=199309L",
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
});
if (options.config) |config| {
const file = try std.fs.path.join(b.allocator, &.{ std.fs.path.dirname(@src().file) orelse ".", "config.h" });
defer b.allocator.free(file);
const content = try std.fs.cwd().readFileAlloc(b.allocator, file, std.math.maxInt(usize));
defer b.allocator.free(content);
var lines = std.mem.splitScalar(u8, content, '\n');
while (lines.next()) |line| {
if (!std.mem.containsAtLeast(u8, line, 1, "SUPPORT")) continue;
if (std.mem.startsWith(u8, line, "//")) continue;
if (std.mem.startsWith(u8, line, "#if")) continue;
var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace
flag = flag["#define ".len - 1 ..]; // Remove #define
flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace
flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
flag = try std.fmt.allocPrint(b.allocator, "-D{s}", .{flag}); // Prepend with -D
// If user specifies the flag skip it
if (std.mem.containsAtLeast(u8, config, 1, flag)) continue;
// Append default value from config.h to compile flags
try raylib_flags_arr.append(b.allocator, flag);
}
// Append config flags supplied by user to compile flags
try raylib_flags_arr.append(b.allocator, config);
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
}
if (options.shared) {
try raylib_flags_arr.appendSlice(b.allocator, shared_flags);
}
const raylib = if (options.shared)
b.addSharedLibrary(.{
.name = "raylib",
.target = target,
.optimize = optimize,
})
else
b.addStaticLibrary(.{
.name = "raylib",
.target = target,
.optimize = optimize,
});
raylib.linkLibC();
// No GLFW required on PLATFORM_DRM
if (options.platform != .drm) {
raylib.addIncludePath(b.path("src/external/glfw/include"));
}
var c_source_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{ "rcore.c", "utils.c" });
if (options.raudio) {
try c_source_files.append("raudio.c");
}
if (options.rmodels) {
try c_source_files.append("rmodels.c");
}
if (options.rshapes) {
try c_source_files.append("rshapes.c");
}
if (options.rtext) {
try c_source_files.append("rtext.c");
}
if (options.rtextures) {
try c_source_files.append("rtextures.c");
}
if (options.opengl_version != .auto) {
raylib.defineCMacro(options.opengl_version.toCMacroStr(), null);
}
switch (target.result.os.tag) {
.windows => {
try c_source_files.append("rglfw.c");
raylib.linkSystemLibrary("winmm");
raylib.linkSystemLibrary("gdi32");
raylib.linkSystemLibrary("opengl32");
setDesktopPlatform(raylib, options.platform);
},
.linux => {
if (options.platform != .drm) {
try c_source_files.append("rglfw.c");
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
raylib.addIncludePath(.{ .cwd_relative = "/usr/include" });
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
raylib.defineCMacro("_GLFW_X11", null);
raylib.linkSystemLibrary("X11");
}
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ Wayland may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
, .{});
@panic("No Wayland");
};
raylib.defineCMacro("_GLFW_WAYLAND", null);
raylib.linkSystemLibrary("wayland-client");
raylib.linkSystemLibrary("wayland-cursor");
raylib.linkSystemLibrary("wayland-egl");
raylib.linkSystemLibrary("xkbcommon");
raylib.addIncludePath(b.path("src"));
waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol");
waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol");
waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol");
waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol");
waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol");
waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol");
waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol");
}
setDesktopPlatform(raylib, options.platform);
} else {
if (options.opengl_version == .auto) {
raylib.linkSystemLibrary("GLESv2");
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
}
raylib.linkSystemLibrary("EGL");
raylib.linkSystemLibrary("drm");
raylib.linkSystemLibrary("gbm");
raylib.linkSystemLibrary("pthread");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("dl");
raylib.addIncludePath(.{ .cwd_relative = "/usr/include/libdrm" });
raylib.defineCMacro("PLATFORM_DRM", null);
raylib.defineCMacro("EGL_NO_X11", null);
raylib.defineCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "2048");
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
try c_source_files.append("rglfw.c");
raylib.linkSystemLibrary("GL");
raylib.linkSystemLibrary("rt");
raylib.linkSystemLibrary("dl");
raylib.linkSystemLibrary("m");
raylib.linkSystemLibrary("X11");
raylib.linkSystemLibrary("Xrandr");
raylib.linkSystemLibrary("Xinerama");
raylib.linkSystemLibrary("Xi");
raylib.linkSystemLibrary("Xxf86vm");
raylib.linkSystemLibrary("Xcursor");
setDesktopPlatform(raylib, options.platform);
},
.macos => {
// On macos rglfw.c include Objective-C files.
try raylib_flags_arr.append(b.allocator, "-ObjC");
raylib.root_module.addCSourceFile(.{
.file = b.path("src/rglfw.c"),
.flags = raylib_flags_arr.items,
});
_ = raylib_flags_arr.pop();
raylib.linkFramework("Foundation");
raylib.linkFramework("CoreServices");
raylib.linkFramework("CoreGraphics");
raylib.linkFramework("AppKit");
raylib.linkFramework("IOKit");
setDesktopPlatform(raylib, options.platform);
},
.emscripten => {
raylib.defineCMacro("PLATFORM_WEB", null);
if (options.opengl_version == .auto) {
raylib.defineCMacro("GRAPHICS_API_OPENGL_ES2", null);
}
if (b.sysroot == null) {
@panic("Pass '--sysroot \"$EMSDK/upstream/emscripten\"'");
}
const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory");
defer b.allocator.free(cache_include);
var dir = std.fs.openDirAbsolute(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
dir.close();
raylib.addIncludePath(.{ .cwd_relative = cache_include });
},
else => {
@panic("Unsupported OS");
},
}
raylib.addIncludePath(b.path("src"));
raylib.root_module.addCSourceFiles(.{
.root = b.path("src"),
.files = c_source_files.items,
.flags = raylib_flags_arr.items,
});
return raylib;
}
/// This function does not need to be called if you passed .raygui = true to addRaylib
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void {
if (raylib_flags_arr.items.len == 0) {
@panic(
\\argument 2 `raylib` in `addRaygui` must come from b.dependency("raylib", ...).artifact("raylib")
);
}
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.addCSourceFile(.{ .file = raygui_c_path, .flags = raylib_flags_arr.items });
raylib.addIncludePath(raygui_dep.path("src"));
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
}
pub const Options = struct {
raudio: bool = true,
rmodels: bool = true,
rshapes: bool = true,
rtext: bool = true,
rtextures: bool = true,
raygui: bool = false,
platform: PlatformBackend = .glfw,
shared: bool = false,
linux_display_backend: LinuxDisplayBackend = .Both,
opengl_version: OpenglVersion = .auto,
/// config should be a list of cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
config: ?[]const u8 = null,
raygui_dependency_name: []const u8 = "raygui",
};
pub const OpenglVersion = enum {
auto,
gl_1_1,
gl_2_1,
gl_3_3,
gl_4_3,
gles_2,
gles_3,
pub fn toCMacroStr(self: @This()) []const u8 {
switch (self) {
.auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
.gl_1_1 => return "GRAPHICS_API_OPENGL_11",
.gl_2_1 => return "GRAPHICS_API_OPENGL_21",
.gl_3_3 => return "GRAPHICS_API_OPENGL_33",
.gl_4_3 => return "GRAPHICS_API_OPENGL_43",
.gles_2 => return "GRAPHICS_API_OPENGL_ES2",
.gles_3 => return "GRAPHICS_API_OPENGL_ES3",
}
}
};
pub const LinuxDisplayBackend = enum {
X11,
Wayland,
Both,
};
pub const PlatformBackend = enum {
glfw,
rgfw,
sdl,
drm,
};
pub fn build(b: *std.Build) !void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const defaults = Options{};
const options = Options{
.platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform,
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
.shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
.config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse null,
};
const lib = try compileRaylib(b, target, optimize, options);
lib.installHeader(b.path("src/raylib.h"), "raylib.h");
lib.installHeader(b.path("src/raymath.h"), "raymath.h");
lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
b.installArtifact(lib);
}
const waylandDir = "src/external/glfw/deps/wayland";
fn waylandGenerate(b: *std.Build, raylib: *std.Build.Step.Compile, comptime protocol: []const u8, comptime basename: []const u8) void {
const protocolDir = waylandDir ++ "/" ++ protocol;
const clientHeader = basename ++ ".h";
const privateCode = basename ++ "-code.h";
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
client_step.addFileArg(b.path(protocolDir));
raylib.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
private_step.addFileArg(b.path(protocolDir));
raylib.addIncludePath(private_step.addOutputFileArg(privateCode).dirname());
raylib.step.dependOn(&client_step.step);
raylib.step.dependOn(&private_step.step);
}

View File

@ -180,7 +180,6 @@
//#define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1

3053
src/external/nanosvg.h vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -185,6 +185,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.flags == 0x40) // No alpha channel
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@ -196,6 +197,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@ -215,6 +217,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@ -236,6 +239,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed
{
int data_size = image_pixel_size*3*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@ -245,6 +249,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed
{
int data_size = image_pixel_size*4*sizeof(unsigned char);
if (header->mipmap_count > 1) data_size = data_size + data_size / 3;
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
@ -265,9 +270,11 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
}
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
{
// NOTE: This forces only 1 mipmap to be loaded which is not really correct but it works
int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
*mips = 1;
int data_size = 0;
// Calculate data size, including all mipmaps
if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size + header->pitch_or_linear_size / 3;
else data_size = header->pitch_or_linear_size;
image_data = RL_MALLOC(data_size*sizeof(unsigned char));

View File

@ -704,7 +704,6 @@ void PollInputEvents(void)
}
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------

View File

@ -1234,7 +1234,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------

View File

@ -69,7 +69,6 @@ void CloseWindow(void);
#define CloseWindow CloseWindow_win32
#define ShowCursor __imp_ShowCursor
#define _APISETSTRING_
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
#endif
#if defined(__APPLE__)
@ -870,7 +869,6 @@ void PollInputEvents(void)
//-----------------------------------------------------------------------------
CORE.Window.resizedLastFrame = false;
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
#define RGFW_HOLD_MOUSE (1L<<2)
if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
@ -883,10 +881,8 @@ void PollInputEvents(void)
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
}
while (RGFW_window_checkEvent(platform.window))
{
if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove))
{
if (!CORE.Input.Gamepad.ready[platform.window->event.joystick])
@ -1196,7 +1192,6 @@ void PollInputEvents(void)
//-----------------------------------------------------------------------------
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
@ -1253,7 +1248,6 @@ int InitPlatform(void)
*/
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
RGFW_window_makeCurrent(platform.window);

View File

@ -1609,7 +1609,6 @@ int InitPlatform(void)
//----------------------------------------------------------------------------
// Define base path for storage
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
CHDIR(CORE.Storage.basePath);
//----------------------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");

View File

@ -1480,7 +1480,6 @@ static void ConfigureEvdevDevice(char *device)
TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
}
if (TEST_BIT(evBits, EV_KEY))
{
// The first 32 keys as defined in input-event-codes.h are pretty much

View File

@ -430,7 +430,6 @@ void PollInputEvents(void)
// TODO: Poll input events for current platform
}
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------

View File

@ -74,6 +74,8 @@
typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device)
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen
int unmaximizedWidth; // Internal var to store the unmaximized window (canvas) width
int unmaximizedHeight; // Internal var to store the unmaximized window (canvas) height
} PlatformData;
//----------------------------------------------------------------------------------
@ -317,7 +319,18 @@ void ToggleBorderlessWindowed(void)
// Set window state: maximized, if resizable
void MaximizeWindow(void)
{
TRACELOG(LOG_WARNING, "MaximizeWindow() not available on target platform");
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
{
platform.unmaximizedWidth = CORE.Window.screen.width;
platform.unmaximizedHeight = CORE.Window.screen.height;
const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0);
const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0);
if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight);
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
}
}
// Set window state: minimized
@ -329,7 +342,12 @@ void MinimizeWindow(void)
// Set window state: not minimized/maximized
void RestoreWindow(void)
{
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
{
if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
}
}
// Set window configuration state using flags
@ -398,9 +416,20 @@ void SetWindowState(unsigned int flags)
}
// State change: FLAG_WINDOW_MAXIMIZED
if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) != (flags & FLAG_WINDOW_MAXIMIZED)) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
{
platform.unmaximizedWidth = CORE.Window.screen.width;
platform.unmaximizedHeight = CORE.Window.screen.height;
const int tabWidth = EM_ASM_INT( { return window.innerWidth; }, 0);
const int tabHeight = EM_ASM_INT( { return window.innerHeight; }, 0);
if (tabWidth && tabHeight) glfwSetWindowSize(platform.handle, tabWidth, tabHeight);
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
}
}
// State change: FLAG_WINDOW_UNFOCUSED
@ -516,9 +545,14 @@ void ClearWindowState(unsigned int flags)
}
// State change: FLAG_WINDOW_MAXIMIZED
if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
{
if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
}
}
// State change: FLAG_WINDOW_UNDECORATED
@ -639,7 +673,9 @@ void SetWindowSize(int width, int height)
// Set window opacity, value opacity is between 0.0 and 1.0
void SetWindowOpacity(float opacity)
{
TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform");
if (opacity >= 1.0f) opacity = 1.0f;
else if (opacity <= 0.0f) opacity = 0.0f;
EM_ASM({ document.getElementById('canvas').style.opacity = $0; }, opacity);
}
// Set window focused
@ -935,7 +971,6 @@ void PollInputEvents(void)
// so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed!
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
// Gamepad support using emscripten API
// NOTE: GLFW3 joystick functionality not available in web

View File

@ -892,8 +892,8 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
return wave;
}
// Checks if wave data is ready
bool IsWaveReady(Wave wave)
// Checks if wave data is valid (data loaded and parameters)
bool IsWaveValid(Wave wave)
{
bool result = false;
@ -993,8 +993,8 @@ Sound LoadSoundAlias(Sound source)
}
// Checks if a sound is ready
bool IsSoundReady(Sound sound)
// Checks if a sound is valid (data loaded and buffers initialized)
bool IsSoundValid(Sound sound)
{
bool result = false;
@ -1726,8 +1726,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music;
}
// Checks if a music stream is ready
bool IsMusicReady(Music music)
// Checks if a music stream is valid (context and buffers initialized)
bool IsMusicValid(Music music)
{
return ((music.ctxData != NULL) && // Validate context loaded
(music.frameCount > 0) && // Validate audio frame count
@ -2119,8 +2119,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream;
}
// Checks if an audio stream is ready
bool IsAudioStreamReady(AudioStream stream)
// Checks if an audio stream is valid (buffers initialized)
bool IsAudioStreamValid(AudioStream stream)
{
return ((stream.buffer != NULL) && // Validate stream buffer
(stream.sampleRate > 0) && // Validate sample rate is supported

View File

@ -1044,7 +1044,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s
// NOTE: Shader functionality is not available on OpenGL 1.1
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
RLAPI bool IsShaderReady(Shader shader); // Check if a shader is ready
RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU)
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
@ -1144,6 +1144,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
// Automation events functionality
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
@ -1211,7 +1215,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
@ -1312,13 +1316,12 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
// NOTE: These functions do not require GPU access
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
RLAPI bool IsImageReady(Image image); // Check if an image is ready
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
@ -1404,9 +1407,9 @@ RLAPI Texture2D LoadTexture(const char *fileName);
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready
RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU)
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready
RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data
@ -1453,7 +1456,7 @@ RLAPI Font LoadFont(const char *fileName);
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI bool IsFontReady(Font font); // Check if a font is ready
RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
@ -1543,7 +1546,7 @@ RLAPI void DrawGrid(int slices, float spacing);
// Model management functions
RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
RLAPI bool IsModelReady(Model model); // Check if a model is ready
RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs)
RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
@ -1586,7 +1589,7 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Material loading/unloading functions
RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
RLAPI bool IsMaterialReady(Material material); // Check if a material is ready
RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU)
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
@ -1624,11 +1627,11 @@ RLAPI float GetMasterVolume(void); // Get mas
// Wave/Sound loading/unloading functions
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready
RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready
RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound
@ -1654,7 +1657,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
RLAPI bool IsMusicReady(Music music); // Checks if a music stream is ready
RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
RLAPI void UnloadMusicStream(Music music); // Unload music stream
RLAPI void PlayMusicStream(Music music); // Start music playing
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
@ -1671,7 +1674,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
// AudioStream management functions
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
RLAPI bool IsAudioStreamReady(AudioStream stream); // Checks if an audio stream is ready
RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill

View File

@ -1,6 +1,6 @@
/**********************************************************************************************
*
* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
*
* CONVENTIONS:
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
@ -12,7 +12,7 @@
* - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside
* - Functions input parameters are always received by value (2 unavoidable exceptions)
* - Functions use always a "result" variable for return
* - Functions use always a "result" variable for return (except C++ operators)
* - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - No compound literals used to make sure libray is compatible with C++
@ -27,6 +27,8 @@
* Define static inline functions code, so #include header suffices for use.
* This may use up lots of memory.
*
* #define RAYMATH_DISABLE_CPP_OPERATORS
* Disables C++ operator overloads for raymath types.
*
* LICENSE: zlib/libpng
*
@ -2580,4 +2582,354 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
}
}
#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS)
// Optional C++ math operators
//-------------------------------------------------------------------------------
// Vector2 operators
static constexpr Vector2 Vector2Zeros = { 0, 0 };
static constexpr Vector2 Vector2Ones = { 1, 1 };
static constexpr Vector2 Vector2UnitX = { 1, 0 };
static constexpr Vector2 Vector2UnitY = { 0, 1 };
inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Add(lhs, rhs);
}
inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Add(lhs, rhs);
return lhs;
}
inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Subtract(lhs, rhs);
}
inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Subtract(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const float& rhs)
{
return Vector2Scale(lhs, rhs);
}
inline const Vector2& operator *= (Vector2& lhs, const float& rhs)
{
lhs = Vector2Scale(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Multiply(lhs, rhs);
}
inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Multiply(lhs, rhs);
return lhs;
}
inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
{
return Vector2Transform(lhs, rhs);
}
inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
{
lhs = Vector2Transform(lhs, rhs);
return lhs;
}
inline Vector2 operator / (const Vector2& lhs, const float& rhs)
{
return Vector2Scale(lhs, 1.0f / rhs);
}
inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
{
lhs = Vector2Scale(lhs, rhs);
return lhs;
}
inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs)
{
return Vector2Divide(lhs, rhs);
}
inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs)
{
lhs = Vector2Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector2& lhs, const Vector2& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y);
}
inline bool operator != (const Vector2& lhs, const Vector2& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y);
}
// Vector3 operators
static constexpr Vector3 Vector3Zeros = { 0, 0, 0 };
static constexpr Vector3 Vector3Ones = { 1, 1, 1 };
static constexpr Vector3 Vector3UnitX = { 1, 0, 0 };
static constexpr Vector3 Vector3UnitY = { 0, 1, 0 };
static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 };
inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Add(lhs, rhs);
}
inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Add(lhs, rhs);
return lhs;
}
inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Subtract(lhs, rhs);
}
inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Subtract(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const float& rhs)
{
return Vector3Scale(lhs, rhs);
}
inline const Vector3& operator *= (Vector3& lhs, const float& rhs)
{
lhs = Vector3Scale(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Multiply(lhs, rhs);
}
inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Multiply(lhs, rhs);
return lhs;
}
inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
{
return Vector3Transform(lhs, rhs);
}
inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
{
lhs = Vector3Transform(lhs, rhs);
return lhs;
}
inline Vector3 operator / (const Vector3& lhs, const float& rhs)
{
return Vector3Scale(lhs, 1.0f / rhs);
}
inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
{
lhs = Vector3Scale(lhs, rhs);
return lhs;
}
inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs)
{
return Vector3Divide(lhs, rhs);
}
inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs)
{
lhs = Vector3Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector3& lhs, const Vector3& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z);
}
inline bool operator != (const Vector3& lhs, const Vector3& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z);
}
// Vector4 operators
static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 };
static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 };
static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 };
static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 };
static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 };
static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 };
inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Add(lhs, rhs);
}
inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Add(lhs, rhs);
return lhs;
}
inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Subtract(lhs, rhs);
}
inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Subtract(lhs, rhs);
return lhs;
}
inline Vector4 operator * (const Vector4& lhs, const float& rhs)
{
return Vector4Scale(lhs, rhs);
}
inline const Vector4& operator *= (Vector4& lhs, const float& rhs)
{
lhs = Vector4Scale(lhs, rhs);
return lhs;
}
inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Multiply(lhs, rhs);
}
inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Multiply(lhs, rhs);
return lhs;
}
inline Vector4 operator / (const Vector4& lhs, const float& rhs)
{
return Vector4Scale(lhs, 1.0f / rhs);
}
inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
{
lhs = Vector4Scale(lhs, rhs);
return lhs;
}
inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs)
{
return Vector4Divide(lhs, rhs);
}
inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs)
{
lhs = Vector4Divide(lhs, rhs);
return lhs;
}
inline bool operator == (const Vector4& lhs, const Vector4& rhs)
{
return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w);
}
inline bool operator != (const Vector4& lhs, const Vector4& rhs)
{
return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w);
}
// Quaternion operators
static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 };
static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 };
static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 };
inline Quaternion operator + (const Quaternion& lhs, const float& rhs)
{
return QuaternionAddValue(lhs, rhs);
}
inline const Quaternion& operator += (Quaternion& lhs, const float& rhs)
{
lhs = QuaternionAddValue(lhs, rhs);
return lhs;
}
inline Quaternion operator - (const Quaternion& lhs, const float& rhs)
{
return QuaternionSubtractValue(lhs, rhs);
}
inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs)
{
lhs = QuaternionSubtractValue(lhs, rhs);
return lhs;
}
inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs)
{
return QuaternionTransform(lhs, rhs);
}
inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs)
{
lhs = QuaternionTransform(lhs, rhs);
return lhs;
}
// Matrix operators
inline Matrix operator + (const Matrix& lhs, const Matrix& rhs)
{
return MatrixAdd(lhs, rhs);
}
inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixAdd(lhs, rhs);
return lhs;
}
inline Matrix operator - (const Matrix& lhs, const Matrix& rhs)
{
return MatrixSubtract(lhs, rhs);
}
inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixSubtract(lhs, rhs);
return lhs;
}
inline Matrix operator * (const Matrix& lhs, const Matrix& rhs)
{
return MatrixMultiply(lhs, rhs);
}
inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs)
{
lhs = MatrixMultiply(lhs, rhs);
return lhs;
}
//-------------------------------------------------------------------------------
#endif // C++ operators
#endif // RAYMATH_H

View File

@ -162,7 +162,6 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
#endif // RCAMERA_H
/***********************************************************************************
*
* CAMERA IMPLEMENTATION

View File

@ -1342,10 +1342,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
return shader;
}
// Check if a shader is ready
bool IsShaderReady(Shader shader)
// Check if a shader is valid (loaded on GPU)
bool IsShaderValid(Shader shader)
{
return ((shader.id > 0) && // Validate shader id (loaded successfully)
return ((shader.id > 0) && // Validate shader id (GPU loaded successfully)
(shader.locs != NULL)); // Validate memory has been allocated for default shader locations
// The following locations are tried to be set automatically (locs[i] >= 0),
@ -2577,6 +2577,265 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
return decodedData;
}
// Compute CRC32 hash code
unsigned int ComputeCRC32(unsigned char *data, int dataSize)
{
static unsigned int crcTable[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unsigned int crc = ~0u;
for (int i = 0; i < dataSize; i++) crc = (crc >> 8) ^ crcTable[data[i] ^ (crc & 0xff)];
return ~crc;
}
// Compute MD5 hash code
// NOTE: Returns a static int[4] array (16 bytes)
unsigned int *ComputeMD5(unsigned char *data, int dataSize)
{
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
static unsigned int hash[4] = { 0 }; // Hash to be returned
// WARNING: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating
// NOTE: r specifies the per-round shift amounts
unsigned int r[] = {
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};
// Using binary integer part of the sines of integers (in radians) as constants
unsigned int k[] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
hash[0] = 0x67452301;
hash[1] = 0xefcdab89;
hash[2] = 0x98badcfe;
hash[3] = 0x10325476;
// Pre-processing: adding a single 1 bit
// Append '1' bit to message
// NOTE: The input bytes are considered as bits strings,
// where the first bit is the most significant bit of the byte
// Pre-processing: padding with zeros
// Append '0' bit until message length in bit 448 (mod 512)
// Append length mod (2 pow 64) to message
int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
memcpy(msg, data, dataSize);
msg[dataSize] = 128; // Write the '1' bit
unsigned int bitsLen = 8*dataSize;
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
for (int offset = 0; offset < newDataSize; offset += (512/8))
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int *w = (unsigned int *)(msg + offset);
// Initialize hash value for this chunk
unsigned int a = hash[0];
unsigned int b = hash[1];
unsigned int c = hash[2];
unsigned int d = hash[3];
for (int i = 0; i < 64; i++)
{
unsigned int f = 0;
unsigned int g = 0;
if (i < 16)
{
f = (b & c) | ((~b) & d);
g = i;
}
else if (i < 32)
{
f = (d & b) | ((~d) & c);
g = (5*i + 1)%16;
}
else if (i < 48)
{
f = b ^ c ^ d;
g = (3*i + 5)%16;
}
else
{
f = c ^ (b | (~d));
g = (7*i)%16;
}
unsigned int temp = d;
d = c;
c = b;
b = b + ROTATE_LEFT((a + f + k[i] + w[g]), r[i]);
a = temp;
}
// Add chunk's hash to result so far
hash[0] += a;
hash[1] += b;
hash[2] += c;
hash[3] += d;
}
RL_FREE(msg);
return hash;
}
// Compute SHA-1 hash code
// NOTE: Returns a static int[5] array (20 bytes)
unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
static unsigned int hash[5] = { 0 }; // Hash to be returned
// Initialize hash values
hash[0] = 0x67452301;
hash[1] = 0xEFCDAB89;
hash[2] = 0x98BADCFE;
hash[3] = 0x10325476;
hash[4] = 0xC3D2E1F0;
// Pre-processing: adding a single 1 bit
// Append '1' bit to message
// NOTE: The input bytes are considered as bits strings,
// where the first bit is the most significant bit of the byte
// Pre-processing: padding with zeros
// Append '0' bit until message length in bit 448 (mod 512)
// Append length mod (2 pow 64) to message
int newDataSize = ((((dataSize + 8)/64) + 1)*64);
unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
memcpy(msg, data, dataSize);
msg[dataSize] = 128; // Write the '1' bit
unsigned int bitsLen = 8*dataSize;
msg[newDataSize-1] = bitsLen;
// Process the message in successive 512-bit chunks
for (int offset = 0; offset < newDataSize; offset += (512/8))
{
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int w[80] = {0};
for (int i = 0; i < 16; i++) {
w[i] = (msg[offset + (i * 4) + 0] << 24) |
(msg[offset + (i * 4) + 1] << 16) |
(msg[offset + (i * 4) + 2] << 8) |
(msg[offset + (i * 4) + 3]);
}
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
for (int i = 16; i < 80; ++i) {
w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
}
// Initialize hash value for this chunk
unsigned int a = hash[0];
unsigned int b = hash[1];
unsigned int c = hash[2];
unsigned int d = hash[3];
unsigned int e = hash[4];
for (int i = 0; i < 80; i++)
{
unsigned int f = 0;
unsigned int k = 0;
if (i < 20) {
f = (b & c) | ((~b) & d);
k = 0x5A827999;
} else if (i < 40) {
f = b ^ c ^ d;
k = 0x6ED9EBA1;
} else if (i < 60) {
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
} else {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
unsigned int temp = ROTATE_LEFT(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = ROTATE_LEFT(b, 30);
b = a;
a = temp;
}
// Add this chunk's hash to result so far
hash[0] += a;
hash[1] += b;
hash[2] += c;
hash[3] += d;
hash[4] += e;
}
free(msg);
return hash;
}
//----------------------------------------------------------------------------------
// Module Functions Definition: Automation Events Recording and Playing
//----------------------------------------------------------------------------------

View File

@ -434,7 +434,7 @@ int GetGestureDetected(void)
return (GESTURES.enabledFlags & GESTURES.current);
}
// Hold time measured in ms
// Hold time measured in seconds
float GetGestureHoldDuration(void)
{
// NOTE: time is calculated on current gesture HOLD

View File

@ -347,7 +347,6 @@
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#endif
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
@ -357,7 +356,6 @@
#endif
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
@ -2474,25 +2472,47 @@ void rlLoadExtensions(void *loader)
}
// Check instanced rendering support
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // Web ANGLE
if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays
{
// Specific check
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
else
{
if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT
(strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
}
else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV");
}
// The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
else if (strstr(extList[i], (const char *)"draw_instanced") != NULL)
{
// GL_ANGLE_draw_instanced doesn't exist
if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0)
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
}
else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0)
{
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
}
// But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
}
// Check NPOT textures support

View File

@ -702,7 +702,6 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
rlPopMatrix();
}
// Draw a wired cylinder with base at startPos and top at endPos
// NOTE: It could be also used for pyramid and cone
void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
@ -1156,8 +1155,8 @@ Model LoadModelFromMesh(Mesh mesh)
return model;
}
// Check if a model is ready
bool IsModelReady(Model model)
// Check if a model is valid (loaded in GPU, VAO/VBOs)
bool IsModelValid(Model model)
{
bool result = false;
@ -1167,7 +1166,23 @@ bool IsModelReady(Model model)
(model.meshCount > 0) && // Validate mesh count
(model.materialCount > 0)) result = true; // Validate material count
// NOTE: This is a very general model validation, many elements could be validated from a model...
// NOTE: Many elements could be validated from a model, including every model mesh VAO/VBOs
// but some VBOs could not be used, it depends on Mesh vertex data
for (int i = 0; i < model.meshCount; i++)
{
if ((model.meshes[i].vertices != NULL) && (model.meshes[i].vboId[0] == 0)) { result = false; break; } // Vertex position buffer not uploaded to GPU
if ((model.meshes[i].texcoords != NULL) && (model.meshes[i].vboId[1] == 0)) { result = false; break; } // Vertex textcoords buffer not uploaded to GPU
if ((model.meshes[i].normals != NULL) && (model.meshes[i].vboId[2] == 0)) { result = false; break; } // Vertex normals buffer not uploaded to GPU
if ((model.meshes[i].colors != NULL) && (model.meshes[i].vboId[3] == 0)) { result = false; break; } // Vertex colors buffer not uploaded to GPU
if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU
if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU
if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU
if ((model.meshes[i].boneIds != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIds buffer not uploaded to GPU
if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
// NOTE: Some OpenGL versions do not support VAO, so we don't check it
//if (model.meshes[i].vaoId == 0) { result = false; break }
}
return result;
}
@ -1259,7 +1274,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
mesh->vaoId = rlLoadVertexArray();
rlEnableVertexArray(mesh->vaoId);
@ -1348,7 +1362,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
if (mesh->boneIds != NULL)
{
// Enable vertex attribute: boneIds (shader-location = 6)
// Enable vertex attribute: boneIds (shader-location = 7)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
@ -1364,7 +1378,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
if (mesh->boneWeights != NULL)
{
// Enable vertex attribute: boneWeights (shader-location = 7)
// Enable vertex attribute: boneWeights (shader-location = 8)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
@ -2098,7 +2112,6 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
return success;
}
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
// Process obj materials
static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
@ -2185,14 +2198,16 @@ Material LoadMaterialDefault(void)
return material;
}
// Check if a material is ready
bool IsMaterialReady(Material material)
// Check if a material is valid (map textures loaded in GPU)
bool IsMaterialValid(Material material)
{
bool result = false;
if ((material.maps != NULL) && // Validate material contain some map
(material.shader.id > 0)) result = true; // Validate material shader is valid
// TODO: Check if available maps contain loaded textures
return result;
}
@ -5229,17 +5244,19 @@ static Model LoadGLTF(const char *fileName)
***********************************************************************************************/
// Macro to simplify attributes loading code
#define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \
#define LOAD_ATTRIBUTE(accesor, numComp, srcType, dstPtr) LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, srcType)
#define LOAD_ATTRIBUTE_CAST(accesor, numComp, srcType, dstPtr, dstType) \
{ \
int n = 0; \
dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \
srcType *buffer = (srcType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(srcType) + accesor->offset/sizeof(srcType); \
for (unsigned int k = 0; k < accesor->count; k++) \
{\
for (int l = 0; l < numComp; l++) \
{\
dstPtr[numComp*k + l] = buffer[n + l];\
dstPtr[numComp*k + l] = (dstType)buffer[n + l];\
}\
n += (int)(accesor->stride/sizeof(dataType));\
n += (int)(accesor->stride/sizeof(srcType));\
}\
}
@ -5680,8 +5697,6 @@ static Model LoadGLTF(const char *fileName)
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
}
// NOTE: Attributes related to animations are processed separately
@ -5702,23 +5717,25 @@ static Model LoadGLTF(const char *fileName)
// Load unsigned short data type into mesh.indices
LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)
}
else if (attribute->component_type == cgltf_component_type_r_8u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count * sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
}
else if (attribute->component_type == cgltf_component_type_r_32u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));
// Load data into a temp buffer to be converted to raylib data type
unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int));
LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp);
// Convert data to raylib indices data type (unsigned short)
for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d];
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
RL_FREE(temp);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
else
{
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
}
}
else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh
@ -5750,7 +5767,7 @@ static Model LoadGLTF(const char *fileName)
// - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file)
// - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets)
//----------------------------------------------------------------------------------------------------
if (data->skins_count == 1)
if (data->skins_count > 0)
{
cgltf_skin skin = data->skins[0];
model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
@ -5770,9 +5787,9 @@ static Model LoadGLTF(const char *fileName)
MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
}
}
else if (data->skins_count > 1)
if (data->skins_count > 1)
{
TRACELOG(LOG_ERROR, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
}
meshIndex = 0;
@ -6093,7 +6110,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
if (result == cgltf_result_success)
{
if (data->skins_count == 1)
if (data->skins_count > 0)
{
cgltf_skin skin = data->skins[0];
*animCount = (int)data->animations_count;
@ -6228,7 +6245,11 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
RL_FREE(boneChannels);
}
}
else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
if (data->skins_count > 1)
{
TRACELOG(LOG_WARNING, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
}
cgltf_free(data);
}

View File

@ -828,8 +828,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
{
if ((lineThick > rec.width) || (lineThick > rec.height))
{
if (rec.width > rec.height) lineThick = rec.height/2;
else if (rec.width < rec.height) lineThick = rec.width/2;
if (rec.width >= rec.height) lineThick = rec.height/2;
else if (rec.width <= rec.height) lineThick = rec.width/2;
}
// When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following

View File

@ -581,17 +581,16 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
return font;
}
// Check if a font is ready
bool IsFontReady(Font font)
// Check if a font is valid (font data loaded)
// WARNING: GPU texture not checked
bool IsFontValid(Font font)
{
return ((font.texture.id > 0) && // Validate OpenGL id for font texture atlas
(font.baseSize > 0) && // Validate font size
return ((font.baseSize > 0) && // Validate font size
(font.glyphCount > 0) && // Validate font contains some glyph
(font.recs != NULL) && // Validate font recs defining glyphs on texture atlas
(font.glyphs != NULL)); // Validate glyph data is loaded
// NOTE: Further validations could be done to verify if recs count and glyphs count
// match glyphCount and to verify that data contained is valid (glyphs values, metrics...)
// NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...)
}
// Load font data for further use
@ -1302,15 +1301,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{
byteCounter++;
int next = 0;
letter = GetCodepointNext(&text[i], &next);
int codepointByteCount = 0;
letter = GetCodepointNext(&text[i], &codepointByteCount);
index = GetGlyphIndex(font, letter);
i += next;
i += codepointByteCount;
if (letter != '\n')
{
if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX;
if (font.glyphs[index].advanceX > 0) textWidth += font.glyphs[index].advanceX;
else textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
}
else
@ -1930,6 +1929,7 @@ int GetCodepointCount(const char *text)
const char *CodepointToUTF8(int codepoint, int *utf8Size)
{
static char utf8[6] = { 0 };
memset(utf8, 0, 6); // Clear static array
int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f)

View File

@ -225,14 +225,6 @@
#pragma GCC diagnostic pop
#endif
#if defined(SUPPORT_FILEFORMAT_SVG)
#define NANOSVG_IMPLEMENTATION // Expands implementation
#include "external/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "external/nanosvgrast.h"
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -335,84 +327,6 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
return image;
}
// Load an image from a SVG file or string with custom size
Image LoadImageSvg(const char *fileNameOrString, int width, int height)
{
Image image = { 0 };
#if defined(SUPPORT_FILEFORMAT_SVG)
bool isSvgStringValid = false;
// Validate fileName or string
if (fileNameOrString != NULL)
{
int dataSize = 0;
unsigned char *fileData = NULL;
if (FileExists(fileNameOrString))
{
fileData = LoadFileData(fileNameOrString, &dataSize);
isSvgStringValid = true;
}
else
{
// Validate fileData as valid SVG string data
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
if ((fileNameOrString != NULL) &&
(fileNameOrString[0] == '<') &&
(fileNameOrString[1] == 's') &&
(fileNameOrString[2] == 'v') &&
(fileNameOrString[3] == 'g'))
{
fileData = (unsigned char *)fileNameOrString;
isSvgStringValid = true;
}
}
if (isSvgStringValid)
{
struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(width*height*4);
// Calculate scales for both the width and the height
const float scaleWidth = width/svgImage->width;
const float scaleHeight = height/svgImage->height;
// Set the largest of the 2 scales to be the scale to use
const float scale = (scaleHeight > scaleWidth)? scaleWidth : scaleHeight;
int offsetX = 0;
int offsetY = 0;
if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale)/2;
else offsetX = (width - svgImage->width*scale)/2;
// Rasterize
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4);
// Populate image struct with all data
image.data = img;
image.width = width;
image.height = height;
image.mipmaps = 1;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
// Free used memory
nsvgDelete(svgImage);
nsvgDeleteRasterizer(rast);
}
if (isSvgStringValid && (fileData != (unsigned char *)fileNameOrString)) UnloadFileData(fileData);
}
#else
TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded");
#endif
return image;
}
// Load animated image data
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
// - Number of frames is returned through 'frames' parameter
@ -592,44 +506,14 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
if (fileData != NULL)
{
qoi_desc desc = { 0 };
image.data = qoi_decode(fileData, dataSize, &desc, 4);
image.data = qoi_decode(fileData, dataSize, &desc, (int) fileData[12]);
image.width = desc.width;
image.height = desc.height;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
image.format = desc.channels == 4 ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8;
image.mipmaps = 1;
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_SVG)
else if ((strcmp(fileType, ".svg") == 0) || (strcmp(fileType, ".SVG") == 0))
{
// Validate fileData as valid SVG string data
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
if ((fileData != NULL) &&
(fileData[0] == '<') &&
(fileData[1] == 's') &&
(fileData[2] == 'v') &&
(fileData[3] == 'g'))
{
struct NSVGimage *svgImage = nsvgParse((char *)fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4);
// Rasterize
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
nsvgRasterize(rast, svgImage, 0, 0, 1.0f, img, svgImage->width, svgImage->height, svgImage->width*4);
// Populate image struct with all data
image.data = img;
image.width = svgImage->width;
image.height = svgImage->height;
image.mipmaps = 1;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
nsvgDelete(svgImage);
nsvgDeleteRasterizer(rast);
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_DDS)
else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0))
{
@ -716,13 +600,13 @@ Image LoadImageFromScreen(void)
}
// Check if an image is ready
bool IsImageReady(Image image)
bool IsImageValid(Image image)
{
bool result = false;
if ((image.data != NULL) && // Validate pixel data available
(image.width > 0) &&
(image.height > 0) && // Validate image size
(image.width > 0) && // Validate image width
(image.height > 0) && // Validate image height
(image.format > 0) && // Validate image format
(image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level)
@ -4085,13 +3969,21 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
// [ ] Support f32bit channels drawing
// TODO: Support PIXELFORMAT_UNCOMPRESSED_R32, PIXELFORMAT_UNCOMPRESSED_R32G32B32, PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 and 16-bit equivalents
// TODO: Support PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 and PIXELFORMAT_UNCOMPRESSED_R1616B16A16
Color colSrc, colDst, blend;
bool blendRequired = true;
// Fast path: Avoid blend if source has no alpha to blend
if ((tint.a == 255) && ((srcPtr->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R5G6B5))) blendRequired = false;
if ((tint.a == 255) &&
((srcPtr->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R5G6B5) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R32) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R16) ||
(srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R16G16B16)))
blendRequired = false;
int strideDst = GetPixelDataSize(dst->width, 1, dst->format);
int bytesPerPixelDst = strideDst/(dst->width);
@ -4340,16 +4232,16 @@ RenderTexture2D LoadRenderTexture(int width, int height)
return target;
}
// Check if a texture is ready
bool IsTextureReady(Texture2D texture)
// Check if a texture is valid (loaded in GPU)
bool IsTextureValid(Texture2D texture)
{
bool result = false;
// TODO: Validate maximum texture size supported by GPU?
// TODO: Validate maximum texture size supported by GPU
if ((texture.id > 0) && // Validate OpenGL id
(texture.width > 0) &&
(texture.height > 0) && // Validate texture size
if ((texture.id > 0) && // Validate OpenGL id (texture uplaoded to GPU)
(texture.width > 0) && // Validate texture width
(texture.height > 0) && // Validate texture height
(texture.format > 0) && // Validate texture pixel format
(texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level)
@ -4367,14 +4259,14 @@ void UnloadTexture(Texture2D texture)
}
}
// Check if a render texture is ready
bool IsRenderTextureReady(RenderTexture2D target)
// Check if a render texture is valid (loaded in GPU)
bool IsRenderTextureValid(RenderTexture2D target)
{
bool result = false;
if ((target.id > 0) && // Validate OpenGL id
IsTextureReady(target.depth) && // Validate FBO depth texture/renderbuffer
IsTextureReady(target.texture)) result = true; // Validate FBO texture
if ((target.id > 0) && // Validate OpenGL id (loaded on GPU)
IsTextureValid(target.depth) && // Validate FBO depth texture/renderbuffer attachment
IsTextureValid(target.texture)) result = true; // Validate FBO texture attachment
return result;
}
@ -4988,8 +4880,6 @@ Vector3 ColorToHSV(Color color)
return hsv;
}
// Get a Color from HSV values
// Implementation reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_conversion
// NOTE: Color->HSV->Color conversion will not yield exactly the same color due to rounding errors

View File

@ -76,7 +76,6 @@ void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = cal
void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader
void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver
#if defined(PLATFORM_ANDROID)
static AAssetManager *assetManager = NULL; // Android assets manager pointer
static const char *internalDataPath = NULL; // Android internal data path