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-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 | | [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) | **???** | | [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 | | [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 | | [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 | | [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 std = @import("std");
const raylib = @import("src/build.zig"); const builtin = @import("builtin");
// This has been tested to work with zig 0.12.0 /// Minimum supported version of Zig
pub fn build(b: *std.Build) !void { const min_ver = "0.12.0";
try raylib.build(b);
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 // NOTE(freakmangd): I don't like using a global here, but it prevents having to
pub const addRaylib = raylib.addRaylib; // get the flags a second time when adding raygui
pub const addRaygui = raylib.addRaygui; 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_button \
textures/textures_sprite_explosion \ textures/textures_sprite_explosion \
textures/textures_srcrec_dstrec \ textures/textures_srcrec_dstrec \
textures/textures_svg_loading \
textures/textures_textured_curve \ textures/textures_textured_curve \
textures/textures_to_image textures/textures_to_image

View File

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

View File

@ -81,7 +81,6 @@ int main(void)
// Update model animation // Update model animation
ModelAnimation anim = modelAnimations[animIndex]; ModelAnimation anim = modelAnimations[animIndex];
animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount; animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount;
UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // 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", "name": "IsShaderValid",
"description": "Check if a shader is ready", "description": "Check if a shader is valid (loaded on GPU)",
"returnType": "bool", "returnType": "bool",
"params": [ "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", "name": "LoadAutomationEventList",
"description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", "description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@ -5186,7 +5231,7 @@
}, },
{ {
"name": "GetGestureHoldDuration", "name": "GetGestureHoldDuration",
"description": "Get gesture hold time in milliseconds", "description": "Get gesture hold time in seconds",
"returnType": "float" "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", "name": "LoadImageAnim",
"description": "Load image sequence from file (frames appended to image.data)", "description": "Load image sequence from file (frames appended to image.data)",
@ -6908,8 +6934,8 @@
"returnType": "Image" "returnType": "Image"
}, },
{ {
"name": "IsImageReady", "name": "IsImageValid",
"description": "Check if an image is ready", "description": "Check if an image is valid (data and parameters)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -8372,8 +8398,8 @@
] ]
}, },
{ {
"name": "IsTextureReady", "name": "IsTextureValid",
"description": "Check if a texture is ready", "description": "Check if a texture is valid (loaded in GPU)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -8394,8 +8420,8 @@
] ]
}, },
{ {
"name": "IsRenderTextureReady", "name": "IsRenderTextureValid",
"description": "Check if a render texture is ready", "description": "Check if a render texture is valid (loaded in GPU)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -8989,8 +9015,8 @@
] ]
}, },
{ {
"name": "IsFontReady", "name": "IsFontValid",
"description": "Check if a font is ready", "description": "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -10281,8 +10307,8 @@
] ]
}, },
{ {
"name": "IsModelReady", "name": "IsModelValid",
"description": "Check if a model is ready", "description": "Check if a model is valid (loaded in GPU, VAO/VBOs)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -10968,8 +10994,8 @@
"returnType": "Material" "returnType": "Material"
}, },
{ {
"name": "IsMaterialReady", "name": "IsMaterialValid",
"description": "Check if a material is ready", "description": "Check if a material is valid (shader assigned, map textures loaded in GPU)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -11343,8 +11369,8 @@
] ]
}, },
{ {
"name": "IsWaveReady", "name": "IsWaveValid",
"description": "Checks if wave data is ready", "description": "Checks if wave data is valid (data loaded and parameters)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -11387,8 +11413,8 @@
] ]
}, },
{ {
"name": "IsSoundReady", "name": "IsSoundValid",
"description": "Checks if a sound is ready", "description": "Checks if a sound is valid (data loaded and buffers initialized)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -11685,8 +11711,8 @@
] ]
}, },
{ {
"name": "IsMusicReady", "name": "IsMusicValid",
"description": "Checks if a music stream is ready", "description": "Checks if a music stream is valid (context and buffers initialized)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {
@ -11874,8 +11900,8 @@
] ]
}, },
{ {
"name": "IsAudioStreamReady", "name": "IsAudioStreamValid",
"description": "Checks if an audio stream is ready", "description": "Checks if an audio stream is valid (buffers initialized)",
"returnType": "bool", "returnType": "bool",
"params": [ "params": [
{ {

View File

@ -3589,8 +3589,8 @@ return {
} }
}, },
{ {
name = "IsShaderReady", name = "IsShaderValid",
description = "Check if a shader is ready", description = "Check if a shader is valid (loaded on GPU)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Shader", name = "shader"} {type = "Shader", name = "shader"}
@ -4190,6 +4190,33 @@ return {
{type = "int *", name = "outputSize"} {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", name = "LoadAutomationEventList",
description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS", description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
@ -4550,7 +4577,7 @@ return {
}, },
{ {
name = "GetGestureHoldDuration", name = "GetGestureHoldDuration",
description = "Get gesture hold time in milliseconds", description = "Get gesture hold time in seconds",
returnType = "float" returnType = "float"
}, },
{ {
@ -5339,16 +5366,6 @@ return {
{type = "int", name = "headerSize"} {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", name = "LoadImageAnim",
description = "Load image sequence from file (frames appended to image.data)", description = "Load image sequence from file (frames appended to image.data)",
@ -5393,8 +5410,8 @@ return {
returnType = "Image" returnType = "Image"
}, },
{ {
name = "IsImageReady", name = "IsImageValid",
description = "Check if an image is ready", description = "Check if an image is valid (data and parameters)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Image", name = "image"} {type = "Image", name = "image"}
@ -6158,8 +6175,8 @@ return {
} }
}, },
{ {
name = "IsTextureReady", name = "IsTextureValid",
description = "Check if a texture is ready", description = "Check if a texture is valid (loaded in GPU)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Texture2D", name = "texture"} {type = "Texture2D", name = "texture"}
@ -6174,8 +6191,8 @@ return {
} }
}, },
{ {
name = "IsRenderTextureReady", name = "IsRenderTextureValid",
description = "Check if a render texture is ready", description = "Check if a render texture is valid (loaded in GPU)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "RenderTexture2D", name = "target"} {type = "RenderTexture2D", name = "target"}
@ -6505,8 +6522,8 @@ return {
} }
}, },
{ {
name = "IsFontReady", name = "IsFontValid",
description = "Check if a font is ready", description = "Check if a font is valid (font data loaded, WARNING: GPU texture not checked)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Font", name = "font"} {type = "Font", name = "font"}
@ -7185,8 +7202,8 @@ return {
} }
}, },
{ {
name = "IsModelReady", name = "IsModelValid",
description = "Check if a model is ready", description = "Check if a model is valid (loaded in GPU, VAO/VBOs)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Model", name = "model"} {type = "Model", name = "model"}
@ -7539,8 +7556,8 @@ return {
returnType = "Material" returnType = "Material"
}, },
{ {
name = "IsMaterialReady", name = "IsMaterialValid",
description = "Check if a material is ready", description = "Check if a material is valid (shader assigned, map textures loaded in GPU)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Material", name = "material"} {type = "Material", name = "material"}
@ -7758,8 +7775,8 @@ return {
} }
}, },
{ {
name = "IsWaveReady", name = "IsWaveValid",
description = "Checks if wave data is ready", description = "Checks if wave data is valid (data loaded and parameters)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Wave", name = "wave"} {type = "Wave", name = "wave"}
@ -7790,8 +7807,8 @@ return {
} }
}, },
{ {
name = "IsSoundReady", name = "IsSoundValid",
description = "Checks if a sound is ready", description = "Checks if a sound is valid (data loaded and buffers initialized)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Sound", name = "sound"} {type = "Sound", name = "sound"}
@ -7980,8 +7997,8 @@ return {
} }
}, },
{ {
name = "IsMusicReady", name = "IsMusicValid",
description = "Checks if a music stream is ready", description = "Checks if a music stream is valid (context and buffers initialized)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "Music", name = "music"} {type = "Music", name = "music"}
@ -8106,8 +8123,8 @@ return {
} }
}, },
{ {
name = "IsAudioStreamReady", name = "IsAudioStreamValid",
description = "Checks if an audio stream is ready", description = "Checks if an audio stream is valid (buffers initialized)",
returnType = "bool", returnType = "bool",
params = { params = {
{type = "AudioStream", name = "stream"} {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="" /> <Param type="unsigned int" name="frames" desc="" />
</Callback> </Callback>
</Callbacks> </Callbacks>
<Functions count="578"> <Functions count="580">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context"> <Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
@ -871,7 +871,7 @@
<Param type="const char *" name="vsCode" desc="" /> <Param type="const char *" name="vsCode" desc="" />
<Param type="const char *" name="fsCode" desc="" /> <Param type="const char *" name="fsCode" desc="" />
</Function> </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="" /> <Param type="Shader" name="shader" desc="" />
</Function> </Function>
<Function name="GetShaderLocation" retType="int" paramCount="2" desc="Get shader uniform location"> <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="const unsigned char *" name="data" desc="" />
<Param type="int *" name="outputSize" desc="" /> <Param type="int *" name="outputSize" desc="" />
</Function> </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"> <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="" /> <Param type="const char *" name="fileName" desc="" />
</Function> </Function>
@ -1269,7 +1281,7 @@
</Function> </Function>
<Function name="GetGestureDetected" retType="int" paramCount="0" desc="Get latest detected gesture"> <Function name="GetGestureDetected" retType="int" paramCount="0" desc="Get latest detected gesture">
</Function> </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>
<Function name="GetGestureDragVector" retType="Vector2" paramCount="0" desc="Get gesture drag vector"> <Function name="GetGestureDragVector" retType="Vector2" paramCount="0" desc="Get gesture drag vector">
</Function> </Function>
@ -1699,11 +1711,6 @@
<Param type="int" name="format" desc="" /> <Param type="int" name="format" desc="" />
<Param type="int" name="headerSize" desc="" /> <Param type="int" name="headerSize" desc="" />
</Function> </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)"> <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="const char *" name="fileName" desc="" />
<Param type="int *" name="frames" desc="" /> <Param type="int *" name="frames" desc="" />
@ -1724,7 +1731,7 @@
</Function> </Function>
<Function name="LoadImageFromScreen" retType="Image" paramCount="0" desc="Load image from screen buffer and (screenshot)"> <Function name="LoadImageFromScreen" retType="Image" paramCount="0" desc="Load image from screen buffer and (screenshot)">
</Function> </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="" /> <Param type="Image" name="image" desc="" />
</Function> </Function>
<Function name="UnloadImage" retType="void" paramCount="1" desc="Unload image from CPU memory (RAM)"> <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="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
</Function> </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="" /> <Param type="Texture2D" name="texture" desc="" />
</Function> </Function>
<Function name="UnloadTexture" retType="void" paramCount="1" desc="Unload texture from GPU memory (VRAM)"> <Function name="UnloadTexture" retType="void" paramCount="1" desc="Unload texture from GPU memory (VRAM)">
<Param type="Texture2D" name="texture" desc="" /> <Param type="Texture2D" name="texture" desc="" />
</Function> </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="" /> <Param type="RenderTexture2D" name="target" desc="" />
</Function> </Function>
<Function name="UnloadRenderTexture" retType="void" paramCount="1" desc="Unload render texture from GPU memory (VRAM)"> <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="codepoints" desc="" />
<Param type="int" name="codepointCount" desc="" /> <Param type="int" name="codepointCount" desc="" />
</Function> </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="" /> <Param type="Font" name="font" desc="" />
</Function> </Function>
<Function name="LoadFontData" retType="GlyphInfo *" paramCount="6" desc="Load font data for further use"> <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)"> <Function name="LoadModelFromMesh" retType="Model" paramCount="1" desc="Load model from generated mesh (default material)">
<Param type="Mesh" name="mesh" desc="" /> <Param type="Mesh" name="mesh" desc="" />
</Function> </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="" /> <Param type="Model" name="model" desc="" />
</Function> </Function>
<Function name="UnloadModel" retType="void" paramCount="1" desc="Unload model (including meshes) from memory (RAM and/or VRAM)"> <Function name="UnloadModel" retType="void" paramCount="1" desc="Unload model (including meshes) from memory (RAM and/or VRAM)">
@ -2794,7 +2801,7 @@
</Function> </Function>
<Function name="LoadMaterialDefault" retType="Material" paramCount="0" desc="Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)"> <Function name="LoadMaterialDefault" retType="Material" paramCount="0" desc="Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)">
</Function> </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="" /> <Param type="Material" name="material" desc="" />
</Function> </Function>
<Function name="UnloadMaterial" retType="void" paramCount="1" desc="Unload material from GPU memory (VRAM)"> <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="const unsigned char *" name="fileData" desc="" />
<Param type="int" name="dataSize" desc="" /> <Param type="int" name="dataSize" desc="" />
</Function> </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="" /> <Param type="Wave" name="wave" desc="" />
</Function> </Function>
<Function name="LoadSound" retType="Sound" paramCount="1" desc="Load sound from file"> <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"> <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="" /> <Param type="Sound" name="source" desc="" />
</Function> </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="" /> <Param type="Sound" name="sound" desc="" />
</Function> </Function>
<Function name="UpdateSound" retType="void" paramCount="3" desc="Update sound buffer with new data"> <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="const unsigned char *" name="data" desc="" />
<Param type="int" name="dataSize" desc="" /> <Param type="int" name="dataSize" desc="" />
</Function> </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="" /> <Param type="Music" name="music" desc="" />
</Function> </Function>
<Function name="UnloadMusicStream" retType="void" paramCount="1" desc="Unload music stream"> <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="sampleSize" desc="" />
<Param type="unsigned int" name="channels" desc="" /> <Param type="unsigned int" name="channels" desc="" />
</Function> </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="" /> <Param type="AudioStream" name="stream" desc="" />
</Function> </Function>
<Function name="UnloadAudioStream" retType="void" paramCount="1" desc="Unload audio stream and free memory"> <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 EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_tiling", "examples\shaders_texture_tiling.vcxproj", "{EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_texture_tiling", "examples\shaders_texture_tiling.vcxproj", "{EFA150D4-F93B-4D7D-A69C-9E8B4663BECD}"
EndProject 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}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_splines_drawing", "examples\shapes_splines_drawing.vcxproj", "{DF25E545-00FF-4E64-844C-7DF98991F901}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_top_down_lights", "examples\shapes_top_down_lights.vcxproj", "{703BE7BA-5B99-4F70-806D-3A259F6A991E}" 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 OBJ_DIR = obj
# Define all object files from source files # 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 = $(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 # For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_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 library instead of rglfw module
USE_EXTERNAL_GLFW ?= FALSE USE_EXTERNAL_GLFW ?= FALSE
# Enable support for both Wayland and X11 by default on Linux when using GLFW # Enable support for X11 by default on Linux when using GLFW
GLFW_LINUX_ENABLE_WAYLAND ?= TRUE # NOTE: Wayland is disabled by default, only enable if you are sure
GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
GLFW_LINUX_ENABLE_X11 ?= TRUE GLFW_LINUX_ENABLE_X11 ?= TRUE
# PLATFORM_DESKTOP_SDL: It requires SDL library to be provided externally # 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_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1 //#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1 //#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1 #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 if (header->ddspf.flags == 0x40) // No alpha channel
{ {
int data_size = image_pixel_size*sizeof(unsigned short); 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); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, 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 if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha
{ {
int data_size = image_pixel_size*sizeof(unsigned short); 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); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, 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 else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{ {
int data_size = image_pixel_size*sizeof(unsigned short); 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); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, 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 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); 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); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, 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 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); 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); image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, 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 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 = 0;
int data_size = (header->pitch_or_linear_size < file_size - 0x80) ? header->pitch_or_linear_size : file_size - 0x80;
*mips = 1; // 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)); image_data = RL_MALLOC(data_size*sizeof(unsigned char));

View File

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

View File

@ -149,7 +149,7 @@ void ToggleFullscreen(void)
{ {
// Store previous window position (in case we exit fullscreen) // Store previous window position (in case we exit fullscreen)
CORE.Window.previousPosition = CORE.Window.position; CORE.Window.previousPosition = CORE.Window.position;
int monitorCount = 0; int monitorCount = 0;
int monitorIndex = GetCurrentMonitor(); int monitorIndex = GetCurrentMonitor();
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount); GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
@ -1234,7 +1234,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE); glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1290,7 +1289,7 @@ int InitPlatform(void)
// Disable GlFW auto iconify behaviour // Disable GlFW auto iconify behaviour
// Auto Iconify automatically minimizes (iconifies) the window if the window loses focus // Auto Iconify automatically minimizes (iconifies) the window if the window loses focus
// additionally auto iconify restores the hardware resolution of the monitor if the window that loses focus is a fullscreen window // additionally auto iconify restores the hardware resolution of the monitor if the window that loses focus is a fullscreen window
glfwWindowHint(GLFW_AUTO_ICONIFY, 0); glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
// Check window creation flags // Check window creation flags
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true; if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;
@ -1580,7 +1579,7 @@ int InitPlatform(void)
int monitorWidth = 0; int monitorWidth = 0;
int monitorHeight = 0; int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight); glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
// Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled. // Here CORE.Window.render.width/height should be used instead of CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled.
int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2; int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2; int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;

View File

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

View File

@ -1609,7 +1609,6 @@ int InitPlatform(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Define base path for storage // Define base path for storage
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
CHDIR(CORE.Storage.basePath);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); 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; TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
} }
if (TEST_BIT(evBits, EV_KEY)) if (TEST_BIT(evBits, EV_KEY))
{ {
// The first 32 keys as defined in input-event-codes.h are pretty much // 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 // TODO: Poll input events for current platform
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -74,6 +74,8 @@
typedef struct { typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device) GLFWwindow *handle; // GLFW window handle (graphic device)
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen 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; } PlatformData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -317,7 +319,18 @@ void ToggleBorderlessWindowed(void)
// Set window state: maximized, if resizable // Set window state: maximized, if resizable
void MaximizeWindow(void) 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 // Set window state: minimized
@ -329,7 +342,12 @@ void MinimizeWindow(void)
// Set window state: not minimized/maximized // Set window state: not minimized/maximized
void RestoreWindow(void) 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 // Set window configuration state using flags
@ -398,9 +416,20 @@ void SetWindowState(unsigned int flags)
} }
// State change: FLAG_WINDOW_MAXIMIZED // 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 // State change: FLAG_WINDOW_UNFOCUSED
@ -516,9 +545,14 @@ void ClearWindowState(unsigned int flags)
} }
// State change: FLAG_WINDOW_MAXIMIZED // 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 // 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 // Set window opacity, value opacity is between 0.0 and 1.0
void SetWindowOpacity(float opacity) 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 // 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! // 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 }; //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
// Gamepad support using emscripten API // Gamepad support using emscripten API
// NOTE: GLFW3 joystick functionality not available in web // 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; return wave;
} }
// Checks if wave data is ready // Checks if wave data is valid (data loaded and parameters)
bool IsWaveReady(Wave wave) bool IsWaveValid(Wave wave)
{ {
bool result = false; bool result = false;
@ -993,8 +993,8 @@ Sound LoadSoundAlias(Sound source)
} }
// Checks if a sound is ready // Checks if a sound is valid (data loaded and buffers initialized)
bool IsSoundReady(Sound sound) bool IsSoundValid(Sound sound)
{ {
bool result = false; bool result = false;
@ -1726,8 +1726,8 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music; return music;
} }
// Checks if a music stream is ready // Checks if a music stream is valid (context and buffers initialized)
bool IsMusicReady(Music music) bool IsMusicValid(Music music)
{ {
return ((music.ctxData != NULL) && // Validate context loaded return ((music.ctxData != NULL) && // Validate context loaded
(music.frameCount > 0) && // Validate audio frame count (music.frameCount > 0) && // Validate audio frame count
@ -2119,8 +2119,8 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream; return stream;
} }
// Checks if an audio stream is ready // Checks if an audio stream is valid (buffers initialized)
bool IsAudioStreamReady(AudioStream stream) bool IsAudioStreamValid(AudioStream stream)
{ {
return ((stream.buffer != NULL) && // Validate stream buffer return ((stream.buffer != NULL) && // Validate stream buffer
(stream.sampleRate > 0) && // Validate sample rate is supported (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 // 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 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 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 GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute 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 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 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 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 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 // Automation events functionality
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS 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 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 bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture 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 Vector2 GetGestureDragVector(void); // Get gesture drag vector
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta 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 // NOTE: These functions do not require GPU access
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) 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 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 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 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 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 LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) 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 // Model management functions
RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) 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 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 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) 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 // Material loading/unloading functions
RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file 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 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 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 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 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 // Wave/Sound loading/unloading functions
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file 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 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 LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data 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 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 UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSound(Sound sound); // Unload sound
@ -1654,7 +1657,7 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions // Music management functions
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file 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 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 UnloadMusicStream(Music music); // Unload music stream
RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI void PlayMusicStream(Music music); // Start music playing
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is 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 // 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 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 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 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 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: * CONVENTIONS:
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all * - 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, * - Functions are always self-contained, no function use another raymath function inside,
* required code is directly re-implemented inside * required code is directly re-implemented inside
* - Functions input parameters are always received by value (2 unavoidable exceptions) * - 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 * - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - No compound literals used to make sure libray is compatible with C++ * - 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. * Define static inline functions code, so #include header suffices for use.
* This may use up lots of memory. * This may use up lots of memory.
* *
* #define RAYMATH_DISABLE_CPP_OPERATORS
* Disables C++ operator overloads for raymath types.
* *
* LICENSE: zlib/libpng * 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 #endif // RAYMATH_H

View File

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

View File

@ -691,7 +691,7 @@ void InitWindow(int width, int height, const char *title)
// Initialize random seed // Initialize random seed
SetRandomSeed((unsigned int)time(NULL)); SetRandomSeed((unsigned int)time(NULL));
TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory()); TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory());
} }
@ -1342,10 +1342,10 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
return shader; return shader;
} }
// Check if a shader is ready // Check if a shader is valid (loaded on GPU)
bool IsShaderReady(Shader shader) 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 (shader.locs != NULL)); // Validate memory has been allocated for default shader locations
// The following locations are tried to be set automatically (locs[i] >= 0), // 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; 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 // Module Functions Definition: Automation Events Recording and Playing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -3457,14 +3716,14 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
break; break;
} }
} }
else else
{ {
if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)) if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0))
{ {
strcpy(files->paths[files->count], path); strcpy(files->paths[files->count], path);
files->count++; files->count++;
} }
if (files->count >= files->capacity) if (files->count >= files->capacity)
{ {
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity); TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);

View File

@ -434,7 +434,7 @@ int GetGestureDetected(void)
return (GESTURES.enabledFlags & GESTURES.current); return (GESTURES.enabledFlags & GESTURES.current);
} }
// Hold time measured in ms // Hold time measured in seconds
float GetGestureHoldDuration(void) float GetGestureHoldDuration(void)
{ {
// NOTE: time is calculated on current gesture HOLD // NOTE: time is calculated on current gesture HOLD
@ -517,7 +517,7 @@ static double rgGetCurrentTime(void)
#if defined(_WIN32) #if defined(_WIN32)
unsigned long long int clockFrequency, currentTime; unsigned long long int clockFrequency, currentTime;
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
QueryPerformanceCounter(&currentTime); QueryPerformanceCounter(&currentTime);
time = (double)currentTime/clockFrequency; // Time in seconds time = (double)currentTime/clockFrequency; // Time in seconds

View File

@ -347,7 +347,6 @@
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#endif #endif
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
@ -357,7 +356,6 @@
#endif #endif
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -2474,25 +2472,47 @@ void rlLoadExtensions(void *loader)
} }
// Check instanced rendering support // 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
{ {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); // Specific check
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true; glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
} glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
else }
{ else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) && // Standard EXT
(strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
{ {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT"); glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
} }
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 // Check NPOT textures support

View File

@ -426,14 +426,14 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
{ {
#if 0 #if 0
// Basic implementation, do not use it! // Basic implementation, do not use it!
// For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls! // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls!
// New optimized version below only requires 4 cos()/sin() calls // New optimized version below only requires 4 cos()/sin() calls
rlPushMatrix(); rlPushMatrix();
// NOTE: Transformation is applied in inverse order (scale -> translate) // NOTE: Transformation is applied in inverse order (scale -> translate)
rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
rlScalef(radius, radius, radius); rlScalef(radius, radius, radius);
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
@ -488,7 +488,7 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
for (int i = 0; i < rings + 1; i++) for (int i = 0; i < rings + 1; i++)
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face
vertices[1] = vertices[3]; vertices[1] = vertices[3];
@ -702,7 +702,6 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
rlPopMatrix(); rlPopMatrix();
} }
// Draw a wired cylinder with base at startPos and top at endPos // Draw a wired cylinder with base at startPos and top at endPos
// NOTE: It could be also used for pyramid and cone // NOTE: It could be also used for pyramid and cone
void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color) void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
@ -1156,8 +1155,8 @@ Model LoadModelFromMesh(Mesh mesh)
return model; return model;
} }
// Check if a model is ready // Check if a model is valid (loaded in GPU, VAO/VBOs)
bool IsModelReady(Model model) bool IsModelValid(Model model)
{ {
bool result = false; bool result = false;
@ -1167,7 +1166,23 @@ bool IsModelReady(Model model)
(model.meshCount > 0) && // Validate mesh count (model.meshCount > 0) && // Validate mesh count
(model.materialCount > 0)) result = true; // Validate material 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; return result;
} }
@ -1259,7 +1274,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
mesh->vaoId = rlLoadVertexArray(); mesh->vaoId = rlLoadVertexArray();
rlEnableVertexArray(mesh->vaoId); rlEnableVertexArray(mesh->vaoId);
@ -1348,7 +1362,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
if (mesh->boneIds != NULL) 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); 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); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
@ -1361,10 +1375,10 @@ void UploadMesh(Mesh *mesh, bool dynamic)
rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4); rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4);
rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
} }
if (mesh->boneWeights != NULL) 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); 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); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
@ -1493,7 +1507,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Upload Bone Transforms // Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{ {
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
@ -1586,7 +1600,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
} }
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{ {
@ -1737,15 +1751,15 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// Upload model normal matrix (if locations available) // Upload model normal matrix (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Upload Bone Transforms // Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices) if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{ {
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount); rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
} }
#endif #endif
//----------------------------------------------------- //-----------------------------------------------------
// Bind active texture maps (if available) // Bind active texture maps (if available)
@ -1831,7 +1845,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
} }
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available) // Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{ {
@ -2098,7 +2112,6 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
return success; return success;
} }
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL) #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
// Process obj materials // Process obj materials
static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount) static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
@ -2185,14 +2198,16 @@ Material LoadMaterialDefault(void)
return material; return material;
} }
// Check if a material is ready // Check if a material is valid (map textures loaded in GPU)
bool IsMaterialReady(Material material) bool IsMaterialValid(Material material)
{ {
bool result = false; bool result = false;
if ((material.maps != NULL) && // Validate material contain some map if ((material.maps != NULL) && // Validate material contain some map
(material.shader.id > 0)) result = true; // Validate material shader is valid (material.shader.id > 0)) result = true; // Validate material shader is valid
// TODO: Check if available maps contain loaded textures
return result; return result;
} }
@ -2353,20 +2368,20 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram
{ {
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL)) if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
{ {
if (frame >= anim.frameCount) frame = frame%anim.frameCount; if (frame >= anim.frameCount) frame = frame%anim.frameCount;
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++)
{ {
if (model.meshes[i].boneMatrices) if (model.meshes[i].boneMatrices)
{ {
assert(model.meshes[i].boneCount == anim.boneCount); assert(model.meshes[i].boneCount == anim.boneCount);
for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++) for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
{ {
Vector3 inTranslation = model.bindPose[boneId].translation; Vector3 inTranslation = model.bindPose[boneId].translation;
Quaternion inRotation = model.bindPose[boneId].rotation; Quaternion inRotation = model.bindPose[boneId].rotation;
Vector3 inScale = model.bindPose[boneId].scale; Vector3 inScale = model.bindPose[boneId].scale;
Vector3 outTranslation = anim.framePoses[frame][boneId].translation; Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
Quaternion outRotation = anim.framePoses[frame][boneId].rotation; Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
Vector3 outScale = anim.framePoses[frame][boneId].scale; Vector3 outScale = anim.framePoses[frame][boneId].scale;
@ -2377,15 +2392,15 @@ void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int fram
Vector3 boneTranslation = Vector3Add( Vector3 boneTranslation = Vector3Add(
Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation), Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
outRotation), outTranslation); outRotation), outTranslation);
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation); Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
Vector3 boneScale = Vector3Multiply(outScale, invScale); Vector3 boneScale = Vector3Multiply(outScale, invScale);
Matrix boneMatrix = MatrixMultiply(MatrixMultiply( Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
QuaternionToMatrix(boneRotation), QuaternionToMatrix(boneRotation),
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
MatrixScale(boneScale.x, boneScale.y, boneScale.z)); MatrixScale(boneScale.x, boneScale.y, boneScale.z));
model.meshes[i].boneMatrices[boneId] = boneMatrix; model.meshes[i].boneMatrices[boneId] = boneMatrix;
} }
} }
@ -4809,12 +4824,12 @@ static Model LoadIQM(const char *fileName)
} }
BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose); BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++)
{ {
model.meshes[i].boneCount = model.boneCount; model.meshes[i].boneCount = model.boneCount;
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
for (int j = 0; j < model.meshes[i].boneCount; j++) for (int j = 0; j < model.meshes[i].boneCount; j++)
{ {
model.meshes[i].boneMatrices[j] = MatrixIdentity(); model.meshes[i].boneMatrices[j] = MatrixIdentity();
@ -5229,17 +5244,19 @@ static Model LoadGLTF(const char *fileName)
***********************************************************************************************/ ***********************************************************************************************/
// Macro to simplify attributes loading code // 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; \ 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 (unsigned int k = 0; k < accesor->count; k++) \
{\ {\
for (int l = 0; l < numComp; l++) \ 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);
} }
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 // 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 unsigned short data type into mesh.indices
LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].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) else if (attribute->component_type == cgltf_component_type_r_32u)
{ {
// Init raylib mesh indices to copy glTF attribute data // Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, 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];
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName); 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 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 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) // - 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]; cgltf_skin skin = data->skins[0];
model.bones = LoadBoneInfoGLTF(skin, &model.boneCount); 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)); 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; meshIndex = 0;
@ -5903,11 +5920,11 @@ static Model LoadGLTF(const char *fileName)
{ {
memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float)); memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));
} }
// Bone Transform Matrices // Bone Transform Matrices
model.meshes[meshIndex].boneCount = model.boneCount; model.meshes[meshIndex].boneCount = model.boneCount;
model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix)); model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
for (int j = 0; j < model.meshes[meshIndex].boneCount; j++) for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
{ {
model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity(); model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity();
@ -6093,7 +6110,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
if (result == cgltf_result_success) if (result == cgltf_result_success)
{ {
if (data->skins_count == 1) if (data->skins_count > 0)
{ {
cgltf_skin skin = data->skins[0]; cgltf_skin skin = data->skins[0];
*animCount = (int)data->animations_count; *animCount = (int)data->animations_count;
@ -6228,7 +6245,11 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
RL_FREE(boneChannels); 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); cgltf_free(data);
} }
@ -6680,7 +6701,7 @@ static Model LoadM3D(const char *fileName)
{ {
memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float)); memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float));
memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float)); memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
model.meshes[i].boneCount = model.boneCount; model.meshes[i].boneCount = model.boneCount;
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix)); model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
for (j = 0; j < model.meshes[i].boneCount; j++) for (j = 0; j < model.meshes[i].boneCount; j++)

View File

@ -828,8 +828,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
{ {
if ((lineThick > rec.width) || (lineThick > rec.height)) if ((lineThick > rec.width) || (lineThick > rec.height))
{ {
if (rec.width > rec.height) lineThick = rec.height/2; if (rec.width >= rec.height) lineThick = rec.height/2;
else if (rec.width < rec.height) lineThick = rec.width/2; else if (rec.width <= rec.height) lineThick = rec.width/2;
} }
// When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following // 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; return font;
} }
// Check if a font is ready // Check if a font is valid (font data loaded)
bool IsFontReady(Font font) // WARNING: GPU texture not checked
bool IsFontValid(Font font)
{ {
return ((font.texture.id > 0) && // Validate OpenGL id for font texture atlas return ((font.baseSize > 0) && // Validate font size
(font.baseSize > 0) && // Validate font size
(font.glyphCount > 0) && // Validate font contains some glyph (font.glyphCount > 0) && // Validate font contains some glyph
(font.recs != NULL) && // Validate font recs defining glyphs on texture atlas (font.recs != NULL) && // Validate font recs defining glyphs on texture atlas
(font.glyphs != NULL)); // Validate glyph data is loaded (font.glyphs != NULL)); // Validate glyph data is loaded
// NOTE: Further validations could be done to verify if recs count and glyphs count // NOTE: Further validations could be done to verify if recs and glyphs contain valid data (glyphs values, metrics...)
// match glyphCount and to verify that data contained is valid (glyphs values, metrics...)
} }
// Load font data for further use // Load font data for further use
@ -677,7 +676,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
{ {
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch); if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch);
// Load characters images // Load characters images
@ -1302,15 +1301,15 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{ {
byteCounter++; byteCounter++;
int next = 0; int codepointByteCount = 0;
letter = GetCodepointNext(&text[i], &next); letter = GetCodepointNext(&text[i], &codepointByteCount);
index = GetGlyphIndex(font, letter); index = GetGlyphIndex(font, letter);
i += next; i += codepointByteCount;
if (letter != '\n') 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 textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
} }
else else
@ -1930,7 +1929,8 @@ int GetCodepointCount(const char *text)
const char *CodepointToUTF8(int codepoint, int *utf8Size) const char *CodepointToUTF8(int codepoint, int *utf8Size)
{ {
static char utf8[6] = { 0 }; static char utf8[6] = { 0 };
int size = 0; // Byte size of codepoint memset(utf8, 0, 6); // Clear static array
int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f) if (codepoint <= 0x7f)
{ {

View File

@ -225,14 +225,6 @@
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #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 // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -335,84 +327,6 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
return image; 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 // Load animated image data
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...] // - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
// - Number of frames is returned through 'frames' parameter // - 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) if (fileData != NULL)
{ {
qoi_desc desc = { 0 }; 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.width = desc.width;
image.height = desc.height; image.height = desc.height;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; image.format = desc.channels == 4 ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8;
image.mipmaps = 1; image.mipmaps = 1;
} }
} }
#endif #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) #if defined(SUPPORT_FILEFORMAT_DDS)
else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0)) else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0))
{ {
@ -716,15 +600,15 @@ Image LoadImageFromScreen(void)
} }
// Check if an image is ready // Check if an image is ready
bool IsImageReady(Image image) bool IsImageValid(Image image)
{ {
bool result = false; bool result = false;
if ((image.data != NULL) && // Validate pixel data available if ((image.data != NULL) && // Validate pixel data available
(image.width > 0) && (image.width > 0) && // Validate image width
(image.height > 0) && // Validate image size (image.height > 0) && // Validate image height
(image.format > 0) && // Validate image format (image.format > 0) && // Validate image format
(image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level) (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level)
return result; return result;
} }
@ -1123,7 +1007,7 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float
// Apply aspect ratio compensation to wider side // Apply aspect ratio compensation to wider side
if (width > height) nx *= aspectRatio; if (width > height) nx *= aspectRatio;
else ny /= aspectRatio; else ny /= aspectRatio;
// Basic perlin noise implementation (not used) // Basic perlin noise implementation (not used)
//float p = (stb_perlin_noise3(nx, ny, 0.0f, 0, 0, 0); //float p = (stb_perlin_noise3(nx, ny, 0.0f, 0, 0, 0);
@ -4085,13 +3969,21 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
// [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend() // [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
// [ ] Support f32bit channels drawing // [ ] 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; Color colSrc, colDst, blend;
bool blendRequired = true; bool blendRequired = true;
// Fast path: Avoid blend if source has no alpha to blend // 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 strideDst = GetPixelDataSize(dst->width, 1, dst->format);
int bytesPerPixelDst = strideDst/(dst->width); int bytesPerPixelDst = strideDst/(dst->width);
@ -4340,16 +4232,16 @@ RenderTexture2D LoadRenderTexture(int width, int height)
return target; return target;
} }
// Check if a texture is ready // Check if a texture is valid (loaded in GPU)
bool IsTextureReady(Texture2D texture) bool IsTextureValid(Texture2D texture)
{ {
bool result = false; 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 if ((texture.id > 0) && // Validate OpenGL id (texture uplaoded to GPU)
(texture.width > 0) && (texture.width > 0) && // Validate texture width
(texture.height > 0) && // Validate texture size (texture.height > 0) && // Validate texture height
(texture.format > 0) && // Validate texture pixel format (texture.format > 0) && // Validate texture pixel format
(texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level) (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 // Check if a render texture is valid (loaded in GPU)
bool IsRenderTextureReady(RenderTexture2D target) bool IsRenderTextureValid(RenderTexture2D target)
{ {
bool result = false; bool result = false;
if ((target.id > 0) && // Validate OpenGL id if ((target.id > 0) && // Validate OpenGL id (loaded on GPU)
IsTextureReady(target.depth) && // Validate FBO depth texture/renderbuffer IsTextureValid(target.depth) && // Validate FBO depth texture/renderbuffer attachment
IsTextureReady(target.texture)) result = true; // Validate FBO texture IsTextureValid(target.texture)) result = true; // Validate FBO texture attachment
return result; return result;
} }
@ -4565,7 +4457,7 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
if (source.width < 0) { flipX = true; source.width *= -1; } if (source.width < 0) { flipX = true; source.width *= -1; }
if (source.height < 0) source.y -= source.height; if (source.height < 0) source.y -= source.height;
if (dest.width < 0) dest.width *= -1; if (dest.width < 0) dest.width *= -1;
if (dest.height < 0) dest.height *= -1; if (dest.height < 0) dest.height *= -1;
@ -4988,8 +4880,6 @@ Vector3 ColorToHSV(Color color)
return hsv; return hsv;
} }
// Get a Color from HSV values // Get a Color from HSV values
// Implementation reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_conversion // 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 // NOTE: Color->HSV->Color conversion will not yield exactly the same color due to rounding errors
@ -5189,10 +5079,10 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
} }
// Get color lerp interpolation between two colors, factor [0.0f..1.0f] // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
Color ColorLerp(Color color1, Color color2, float factor) Color ColorLerp(Color color1, Color color2, float factor)
{ {
Color color = { 0 }; Color color = { 0 };
if (factor < 0.0f) factor = 0.0f; if (factor < 0.0f) factor = 0.0f;
else if (factor > 1.0f) factor = 1.0f; else if (factor > 1.0f) factor = 1.0f;

View File

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