Merge branch 'raysan5:master' into master

This commit is contained in:
Colleague Riley 2024-10-21 16:15:38 -04:00 committed by GitHub
commit 078656f85a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
60 changed files with 5221 additions and 7035 deletions

View File

@ -9,7 +9,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib](https://github.com/raysan5/raylib) | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | | [raylib](https://github.com/raysan5/raylib) | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.0** | [Beef](https://www.beeflang.org) | MIT | | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.0** | [Beef](https://www.beeflang.org) | MIT |
| [raylib-boo](https://github.com/Rabios/raylib-boo) | 3.7 | [Boo](http://boo-language.github.io) | MIT | | [raylib-boo](https://github.com/Rabios/raylib-boo) | 3.7 | [Boo](http://boo-language.github.io) | MIT |
| [raybit](https://github.com/Alex-Velez/raybit) | 3.7 | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | | [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
| [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
@ -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 |
@ -78,10 +78,10 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib | | [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib | | [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD | | [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT | | [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT | | [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 | | [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | 4.5 | [Lean4](https://lean-lang.org) | BSD-3-Clause | | [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain | | [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT | | [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
@ -92,6 +92,7 @@ These are utility wrappers for specific languages, they are not required to use
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: | | ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | | [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib | | [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
### Older or Unmaintained Language Bindings ### Older or Unmaintained Language Bindings

View File

@ -3,6 +3,17 @@ changelog
Current Release: raylib 5.0 (18 November 2023) Current Release: raylib 5.0 (18 November 2023)
-------------------------------------------------------------------------
Release: raylib 5.5 - 11th Anniversary Edition? (18 November 2024?)
-------------------------------------------------------------------------
KEY CHANGES:
-
-
-
Detailed changes:
...
------------------------------------------------------------------------- -------------------------------------------------------------------------
Release: raylib 5.0 - 10th Anniversary Edition (18 November 2023) Release: raylib 5.0 - 10th Anniversary Edition (18 November 2023)
------------------------------------------------------------------------- -------------------------------------------------------------------------

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

@ -100,7 +100,8 @@ elseif ("${PLATFORM}" MATCHES "SDL")
endif () endif ()
if (NOT ${OPENGL_VERSION} MATCHES "OFF") if (NOT ${OPENGL_VERSION} MATCHES "OFF")
set(${SUGGESTED_GRAPHICS} "${GRAPHICS}") set(SUGGESTED_GRAPHICS "${GRAPHICS}")
if (${OPENGL_VERSION} MATCHES "4.3") if (${OPENGL_VERSION} MATCHES "4.3")
set(GRAPHICS "GRAPHICS_API_OPENGL_43") set(GRAPHICS "GRAPHICS_API_OPENGL_43")
elseif (${OPENGL_VERSION} MATCHES "3.3") elseif (${OPENGL_VERSION} MATCHES "3.3")
@ -114,8 +115,8 @@ if (NOT ${OPENGL_VERSION} MATCHES "OFF")
elseif (${OPENGL_VERSION} MATCHES "ES 3.0") elseif (${OPENGL_VERSION} MATCHES "ES 3.0")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES3") set(GRAPHICS "GRAPHICS_API_OPENGL_ES3")
endif () endif ()
if ("${SUGGESTED_GRAPHICS}" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}") if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}")
message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail") message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.")
endif () endif ()
endif () endif ()

View File

@ -70,8 +70,9 @@ RAYLIB_SRC_PATH ?= ../src
# Locations of raylib.h and libraylib.a/libraylib.so # Locations of raylib.h and libraylib.a/libraylib.so
# NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD
RAYLIB_INCLUDE_PATH ?= /usr/local/include DESTDIR ?= /usr/local
RAYLIB_LIB_PATH ?= /usr/local/lib RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include
RAYLIB_LIB_PATH ?= $(DESTDIR)/lib
# Library type compilation: STATIC (.a) or SHARED (.so/.dll) # Library type compilation: STATIC (.a) or SHARED (.so/.dll)
RAYLIB_LIBTYPE ?= STATIC RAYLIB_LIBTYPE ?= STATIC
@ -491,6 +492,7 @@ CORE = \
core/core_input_mouse \ core/core_input_mouse \
core/core_input_mouse_wheel \ core/core_input_mouse_wheel \
core/core_input_multitouch \ core/core_input_multitouch \
core/core_input_virtual_controls \
core/core_loading_thread \ core/core_loading_thread \
core/core_random_sequence \ core/core_random_sequence \
core/core_random_values \ core/core_random_values \
@ -547,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
@ -582,10 +583,12 @@ MODELS = \
models/models_mesh_generation \ models/models_mesh_generation \
models/models_mesh_picking \ models/models_mesh_picking \
models/models_orthographic_projection \ models/models_orthographic_projection \
models/models_point_rendering \
models/models_rlgl_solar_system \ models/models_rlgl_solar_system \
models/models_skybox \ models/models_skybox \
models/models_waving_cubes \ models/models_waving_cubes \
models/models_yaw_pitch_roll models/models_yaw_pitch_roll \
models/models_gpu_skinning
SHADERS = \ SHADERS = \
shaders/shaders_basic_lighting \ shaders/shaders_basic_lighting \

View File

@ -35,8 +35,9 @@ RAYLIB_PATH ?= ..
# Locations of raylib.h and libraylib.a/libraylib.so # Locations of raylib.h and libraylib.a/libraylib.so
# NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD
RAYLIB_INCLUDE_PATH ?= /usr/local/include DESTDIR ?= /usr/local
RAYLIB_LIB_PATH ?= /usr/local/lib RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include
RAYLIB_LIB_PATH ?= $(DESTDIR)/lib
# Library type compilation: STATIC (.a) or SHARED (.so/.dll) # Library type compilation: STATIC (.a) or SHARED (.so/.dll)
RAYLIB_LIBTYPE ?= STATIC RAYLIB_LIBTYPE ?= STATIC
@ -358,6 +359,7 @@ CORE = \
core/core_input_mouse \ core/core_input_mouse \
core/core_input_mouse_wheel \ core/core_input_mouse_wheel \
core/core_input_multitouch \ core/core_input_multitouch \
core/core_input_virtual_controls \
core/core_loading_thread \ core/core_loading_thread \
core/core_random_sequence \ core/core_random_sequence \
core/core_random_values \ core/core_random_values \
@ -413,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
@ -447,6 +448,7 @@ MODELS = \
models/models_mesh_generation \ models/models_mesh_generation \
models/models_mesh_picking \ models/models_mesh_picking \
models/models_orthographic_projection \ models/models_orthographic_projection \
models/models_point_rendering \
models/models_rlgl_solar_system \ models/models_rlgl_solar_system \
models/models_skybox \ models/models_skybox \
models/models_waving_cubes \ models/models_waving_cubes \
@ -773,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

@ -31,31 +31,32 @@ Examples using raylib core platform functionality like window creation, inputs,
| 05 | [core_input_gamepad](core/core_input_gamepad.c) | <img src="core/core_input_gamepad.png" alt="core_input_gamepad" width="80"> | ⭐️☆☆☆ | 1.1 | **4.2** | [Ray](https://github.com/raysan5) | | 05 | [core_input_gamepad](core/core_input_gamepad.c) | <img src="core/core_input_gamepad.png" alt="core_input_gamepad" width="80"> | ⭐️☆☆☆ | 1.1 | **4.2** | [Ray](https://github.com/raysan5) |
| 06 | [core_input_multitouch](core/core_input_multitouch.c) | <img src="core/core_input_multitouch.png" alt="core_input_multitouch" width="80"> | ⭐️☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) | | 06 | [core_input_multitouch](core/core_input_multitouch.c) | <img src="core/core_input_multitouch.png" alt="core_input_multitouch" width="80"> | ⭐️☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) |
| 07 | [core_input_gestures](core/core_input_gestures.c) | <img src="core/core_input_gestures.png" alt="core_input_gestures" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | | 07 | [core_input_gestures](core/core_input_gestures.c) | <img src="core/core_input_gestures.png" alt="core_input_gestures" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) |
| 08 | [core_2d_camera](core/core_2d_camera.c) | <img src="core/core_2d_camera.png" alt="core_2d_camera" width="80"> | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) | | 08 | [core_input_virtual_controls](core/core_input_virtual_controls.c) | <img src="core/core_input_virtual_controls.png" alt="core_input_virtual_controls" width="80"> | ⭐️⭐️☆☆ | **5.0** | **5.0** | [oblerion](https://github.com/oblerion) |
| 09 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | <img src="core/core_2d_camera_mouse_zoom.png" alt="core_2d_camera_mouse_zoom" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | | 09 | [core_2d_camera](core/core_2d_camera.c) | <img src="core/core_2d_camera.png" alt="core_2d_camera" width="80"> | ⭐️⭐️☆☆ | 1.5 | 3.0 | [Ray](https://github.com/raysan5) |
| 10 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | <img src="core/core_2d_camera_platformer.png" alt="core_2d_camera_platformer" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) | | 10 | [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | <img src="core/core_2d_camera_mouse_zoom.png" alt="core_2d_camera_mouse_zoom" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) |
| 11 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | <img src="core/core_2d_camera_split_screen.png" alt="core_2d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) | | 11 | [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | <img src="core/core_2d_camera_platformer.png" alt="core_2d_camera_platformer" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [avyy](https://github.com/avyy) |
| 12 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | <img src="core/core_3d_camera_mode.png" alt="core_3d_camera_mode" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 12 | [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | <img src="core/core_2d_camera_split_screen.png" alt="core_2d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | **4.5** | **4.5** | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) |
| 13 | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 13 | [core_3d_camera_mode](core/core_3d_camera_mode.c) | <img src="core/core_3d_camera_mode.png" alt="core_3d_camera_mode" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
| 14 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 14 | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 15 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) | | 15 | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 16 | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 16 | [core_3d_camera:split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.0** | [Jeffery Myers](https://github.com/JeffM2501) |
| 17 | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) | | 17 | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 18 | [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | 18 | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.4 | [Ray](https://github.com/raysan5) |
| 19 | [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | | 19 | [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) |
| 20 | [core_window_letterbox](core/core_window_letterbox.c) | <img src="core/core_window_letterbox.png" alt="core_window_letterbox" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) | | 20 | [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐️⭐️⭐️☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 21 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 21 | [core_window_letterbox](core/core_window_letterbox.c) | <img src="core/core_window_letterbox.png" alt="core_window_letterbox" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Anata](https://github.com/anatagawa) |
| 22 | [core_drop_files](core/core_drop_files.c) | <img src="core/core_drop_files.png" alt="core_drop_files" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | | 22 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
| 23 | [core_random_values](core/core_random_values.c) | <img src="core/core_random_values.png" alt="core_random_values" width="80"> | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) | | 23 | [core_drop_files](core/core_drop_files.c) | <img src="core/core_drop_files.png" alt="core_drop_files" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
| 24 | [core_storage_values](core/core_storage_values.c) | <img src="core/core_storage_values.png" alt="core_storage_values" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) | | 24 | [core_random_values](core/core_random_values.c) | <img src="core/core_random_values.png" alt="core_random_values" width="80"> | ⭐️☆☆☆ | 1.1 | 1.1 | [Ray](https://github.com/raysan5) |
| 25 | [core_vr_simulator](core/core_vr_simulator.c) | <img src="core/core_vr_simulator.png" alt="core_vr_simulator" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | | 25 | [core_storage_values](core/core_storage_values.c) | <img src="core/core_storage_values.png" alt="core_storage_values" width="80"> | ⭐️⭐️☆☆ | 1.4 | **4.2** | [Ray](https://github.com/raysan5) |
| 26 | [core_loading_thread](core/core_loading_thread.c) | <img src="core/core_loading_thread.png" alt="core_loading_thread" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) | | 26 | [core_vr_simulator](core/core_vr_simulator.c) | <img src="core/core_vr_simulator.png" alt="core_vr_simulator" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) |
| 27 | [core_scissor_test](core/core_scissor_test.c) | <img src="core/core_scissor_test.png" alt="core_scissor_test" width="80"> | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | | 27 | [core_loading_thread](core/core_loading_thread.c) | <img src="core/core_loading_thread.png" alt="core_loading_thread" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Ray](https://github.com/raysan5) |
| 28 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | <img src="core/core_basic_screen_manager.png" alt="core_basic_screen_manager" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | | 28 | [core_scissor_test](core/core_scissor_test.c) | <img src="core/core_scissor_test.png" alt="core_scissor_test" width="80"> | ⭐️☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| 29 | [core_custom_frame_control](core/core_custom_frame_control.c) | <img src="core/core_custom_frame_control.png" alt="core_custom_frame_control" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) | | 29 | [core_basic_screen_manager](core/core_basic_screen_manager.c) | <img src="core/core_basic_screen_manager.png" alt="core_basic_screen_manager" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) |
| 30 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | | 30 | [core_custom_frame_control](core/core_custom_frame_control.c) | <img src="core/core_custom_frame_control.png" alt="core_custom_frame_control" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Ray](https://github.com/raysan5) |
| 31 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 31 | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐️⭐️⭐️☆ | 3.7 | **4.0** | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) |
| 32 | [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐️☆☆☆ | **5.0** | **5.0** | [REDl3east](https://github.com/REDl3east) | | 32 | [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐️⭐️☆☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
| 33 | [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐️☆☆☆ | **5.0** | **5.0** | [REDl3east](https://github.com/REDl3east) |
### category: shapes ### category: shapes
@ -63,22 +64,22 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 31 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | <img src="shapes/shapes_basic_shapes.png" alt="shapes_basic_shapes" width="80"> | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) | | 34 | [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | <img src="shapes/shapes_basic_shapes.png" alt="shapes_basic_shapes" width="80"> | ⭐️☆☆☆ | 1.0 | **4.0** | [Ray](https://github.com/raysan5) |
| 32 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | <img src="shapes/shapes_bouncing_ball.png" alt="shapes_bouncing_ball" width="80"> | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 35 | [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | <img src="shapes/shapes_bouncing_ball.png" alt="shapes_bouncing_ball" width="80"> | ⭐️☆☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 33 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | <img src="shapes/shapes_colors_palette.png" alt="shapes_colors_palette" width="80"> | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) | | 36 | [shapes_colors_palette](shapes/shapes_colors_palette.c) | <img src="shapes/shapes_colors_palette.png" alt="shapes_colors_palette" width="80"> | ⭐️⭐️☆☆ | 1.0 | 2.5 | [Ray](https://github.com/raysan5) |
| 34 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | <img src="shapes/shapes_logo_raylib.png" alt="shapes_logo_raylib" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 37 | [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | <img src="shapes/shapes_logo_raylib.png" alt="shapes_logo_raylib" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
| 35 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | <img src="shapes/shapes_logo_raylib_anim.png" alt="shapes_logo_raylib_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | | 38 | [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | <img src="shapes/shapes_logo_raylib_anim.png" alt="shapes_logo_raylib_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) |
| 36 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | <img src="shapes/shapes_rectangle_scaling.png" alt="shapes_rectangle_scaling" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 39 | [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | <img src="shapes/shapes_rectangle_scaling.png" alt="shapes_rectangle_scaling" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| 37 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | <img src="shapes/shapes_lines_bezier.png" alt="shapes_lines_bezier" width="80"> | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) | | 40 | [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | <img src="shapes/shapes_lines_bezier.png" alt="shapes_lines_bezier" width="80"> | ⭐️☆☆☆ | 1.7 | 1.7 | [Ray](https://github.com/raysan5) |
| 38 | [shapes_collision_area](shapes/shapes_collision_area.c) | <img src="shapes/shapes_collision_area.png" alt="shapes_collision_area" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 41 | [shapes_collision_area](shapes/shapes_collision_area.c) | <img src="shapes/shapes_collision_area.png" alt="shapes_collision_area" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 39 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | <img src="shapes/shapes_following_eyes.png" alt="shapes_following_eyes" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 42 | [shapes_following_eyes](shapes/shapes_following_eyes.c) | <img src="shapes/shapes_following_eyes.png" alt="shapes_following_eyes" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 40 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | <img src="shapes/shapes_easings_ball_anim.png" alt="shapes_easings_ball_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 43 | [shapes_easings_ball_anim](shapes/shapes_easings_ball_anim.c) | <img src="shapes/shapes_easings_ball_anim.png" alt="shapes_easings_ball_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 41 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | <img src="shapes/shapes_easings_box_anim.png" alt="shapes_easings_box_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 44 | [shapes_easings_box_anim](shapes/shapes_easings_box_anim.c) | <img src="shapes/shapes_easings_box_anim.png" alt="shapes_easings_box_anim" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 42 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | <img src="shapes/shapes_easings_rectangle_array.png" alt="shapes_easings_rectangle_array" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 45 | [shapes_easings_rectangle_array](shapes/shapes_easings_rectangle_array.c) | <img src="shapes/shapes_easings_rectangle_array.png" alt="shapes_easings_rectangle_array" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 43 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | <img src="shapes/shapes_draw_ring.png" alt="shapes_draw_ring" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 46 | [shapes_draw_ring](shapes/shapes_draw_ring.c) | <img src="shapes/shapes_draw_ring.png" alt="shapes_draw_ring" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| 44 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | <img src="shapes/shapes_draw_circle_sector.png" alt="shapes_draw_circle_sector" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 47 | [shapes_draw_circle_sector](shapes/shapes_draw_circle_sector.c) | <img src="shapes/shapes_draw_circle_sector.png" alt="shapes_draw_circle_sector" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| 45 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | <img src="shapes/shapes_draw_rectangle_rounded.png" alt="shapes_draw_rectangle_rounded" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | 48 | [shapes_draw_rectangle_rounded](shapes/shapes_draw_rectangle_rounded.c) | <img src="shapes/shapes_draw_rectangle_rounded.png" alt="shapes_draw_rectangle_rounded" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| 46 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | <img src="shapes/shapes_top_down_lights.png" alt="shapes_top_down_lights" width="80"> | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) | | 49 | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | <img src="shapes/shapes_top_down_lights.png" alt="shapes_top_down_lights" width="80"> | ⭐️⭐️⭐️⭐️ | **4.2** | **4.2** | [Jeffery Myers](https://github.com/JeffM2501) |
### category: textures ### category: textures
@ -86,28 +87,28 @@ Examples using raylib textures functionality, including image/textures loading/g
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 47 | [textures_logo_raylib](textures/textures_logo_raylib.c) | <img src="textures/textures_logo_raylib.png" alt="textures_logo_raylib" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 50 | [textures_logo_raylib](textures/textures_logo_raylib.c) | <img src="textures/textures_logo_raylib.png" alt="textures_logo_raylib" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
| 48 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | <img src="textures/textures_srcrec_dstrec.png" alt="textures_srcrec_dstrec" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 51 | [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | <img src="textures/textures_srcrec_dstrec.png" alt="textures_srcrec_dstrec" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 49 | [textures_image_drawing](textures/textures_image_drawing.c) | <img src="textures/textures_image_drawing.png" alt="textures_image_drawing" width="80"> | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | | 52 | [textures_image_drawing](textures/textures_image_drawing.c) | <img src="textures/textures_image_drawing.png" alt="textures_image_drawing" width="80"> | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) |
| 50 | [textures_image_generation](textures/textures_image_generation.c) | <img src="textures/textures_image_generation.png" alt="textures_image_generation" width="80"> | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Ray](https://github.com/raysan5) | | 53 | [textures_image_generation](textures/textures_image_generation.c) | <img src="textures/textures_image_generation.png" alt="textures_image_generation" width="80"> | ⭐️⭐️☆☆ | 1.8 | 1.8 | [Ray](https://github.com/raysan5) |
| 51 | [textures_image_loading](textures/textures_image_loading.c) | <img src="textures/textures_image_loading.png" alt="textures_image_loading" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 54 | [textures_image_loading](textures/textures_image_loading.c) | <img src="textures/textures_image_loading.png" alt="textures_image_loading" width="80"> | ⭐️☆☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 52 | [textures_image_processing](textures/textures_image_processing.c) | <img src="textures/textures_image_processing.png" alt="textures_image_processing" width="80"> | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) | | 55 | [textures_image_processing](textures/textures_image_processing.c) | <img src="textures/textures_image_processing.png" alt="textures_image_processing" width="80"> | ⭐️⭐️⭐️☆ | 1.4 | 3.5 | [Ray](https://github.com/raysan5) |
| 53 | [textures_image_text](textures/textures_image_text.c) | <img src="textures/textures_image_text.png" alt="textures_image_text" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | | 56 | [textures_image_text](textures/textures_image_text.c) | <img src="textures/textures_image_text.png" alt="textures_image_text" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) |
| 54 | [textures_to_image](textures/textures_to_image.c) | <img src="textures/textures_to_image.png" alt="textures_to_image" width="80"> | ⭐️☆☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 57 | [textures_to_image](textures/textures_to_image.c) | <img src="textures/textures_to_image.png" alt="textures_to_image" width="80"> | ⭐️☆☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 55 | [textures_raw_data](textures/textures_raw_data.c) | <img src="textures/textures_raw_data.png" alt="textures_raw_data" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | | 58 | [textures_raw_data](textures/textures_raw_data.c) | <img src="textures/textures_raw_data.png" alt="textures_raw_data" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) |
| 56 | [textures_particles_blending](textures/textures_particles_blending.c) | <img src="textures/textures_particles_blending.png" alt="textures_particles_blending" width="80"> | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | | 59 | [textures_particles_blending](textures/textures_particles_blending.c) | <img src="textures/textures_particles_blending.png" alt="textures_particles_blending" width="80"> | ⭐️☆☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) |
| 57 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | <img src="textures/textures_npatch_drawing.png" alt="textures_npatch_drawing" width="80"> | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) | | 60 | [textures_npatch_drawing](textures/textures_npatch_drawing.c) | <img src="textures/textures_npatch_drawing.png" alt="textures_npatch_drawing" width="80"> | ⭐️⭐️⭐️☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) |
| 58 | [textures_background_scrolling](textures/textures_background_scrolling.c) | <img src="textures/textures_background_scrolling.png" alt="textures_background_scrolling" width="80"> | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) | | 61 | [textures_background_scrolling](textures/textures_background_scrolling.c) | <img src="textures/textures_background_scrolling.png" alt="textures_background_scrolling" width="80"> | ⭐️☆☆☆ | 2.0 | 2.5 | [Ray](https://github.com/raysan5) |
| 59 | [textures_sprite_anim](textures/textures_sprite_anim.c) | <img src="textures/textures_sprite_anim.png" alt="textures_sprite_anim" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) | | 62 | [textures_sprite_anim](textures/textures_sprite_anim.c) | <img src="textures/textures_sprite_anim.png" alt="textures_sprite_anim" width="80"> | ⭐️⭐️☆☆ | 1.3 | 1.3 | [Ray](https://github.com/raysan5) |
| 60 | [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) | | 63 | [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐️⭐️☆☆ | 2.5 | 2.5 | [Ray](https://github.com/raysan5) |
| 61 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | | 64 | [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 62 | [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) | | 65 | [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | 2.5 | [Ray](https://github.com/raysan5) |
| 63 | [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) | | 66 | [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| 64 | [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) | | 67 | [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐️☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) |
| 65 | [textures_draw_tiled](textures/textures_draw_tiled.c) | <img src="textures/textures_draw_tiled.png" alt="textures_draw_tiled" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | **4.2** | [Vlad Adrian](https://github.com/demizdor) | | 68 | [textures_draw_tiled](textures/textures_draw_tiled.c) | <img src="textures/textures_draw_tiled.png" alt="textures_draw_tiled" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | **4.2** | [Vlad Adrian](https://github.com/demizdor) |
| 66 | [textures_polygon](textures/textures_polygon.c) | <img src="textures/textures_polygon.png" alt="textures_polygon" width="80"> | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/codifies) | | 69 | [textures_polygon](textures/textures_polygon.c) | <img src="textures/textures_polygon.png" alt="textures_polygon" width="80"> | ⭐️☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/codifies) |
| 67 | [textures_fog_of_war](textures/textures_fog_of_war.c) | <img src="textures/textures_fog_of_war.png" alt="textures_fog_of_war" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 70 | [textures_fog_of_war](textures/textures_fog_of_war.c) | <img src="textures/textures_fog_of_war.png" alt="textures_fog_of_war" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
| 68 | [textures_gif_player](textures/textures_gif_player.c) | <img src="textures/textures_gif_player.png" alt="textures_gif_player" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 71 | [textures_gif_player](textures/textures_gif_player.c) | <img src="textures/textures_gif_player.png" alt="textures_gif_player" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
### category: text ### category: text
@ -115,18 +116,18 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 69 | [text_raylib_fonts](text/text_raylib_fonts.c) | <img src="text/text_raylib_fonts.png" alt="text_raylib_fonts" width="80"> | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | | 72 | [text_raylib_fonts](text/text_raylib_fonts.c) | <img src="text/text_raylib_fonts.png" alt="text_raylib_fonts" width="80"> | ⭐️☆☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) |
| 70 | [text_font_spritefont](text/text_font_spritefont.c) | <img src="text/text_font_spritefont.png" alt="text_font_spritefont" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | | 73 | [text_font_spritefont](text/text_font_spritefont.c) | <img src="text/text_font_spritefont.png" alt="text_font_spritefont" width="80"> | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
| 71 | [text_font_filters](text/text_font_filters.c) | <img src="text/text_font_filters.png" alt="text_font_filters" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | | 74 | [text_font_filters](text/text_font_filters.c) | <img src="text/text_font_filters.png" alt="text_font_filters" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
| 72 | [text_font_loading](text/text_font_loading.c) | <img src="text/text_font_loading.png" alt="text_font_loading" width="80"> | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) | | 75 | [text_font_loading](text/text_font_loading.c) | <img src="text/text_font_loading.png" alt="text_font_loading" width="80"> | ⭐️☆☆☆ | 1.4 | 3.0 | [Ray](https://github.com/raysan5) |
| 73 | [text_font_sdf](text/text_font_sdf.c) | <img src="text/text_font_sdf.png" alt="text_font_sdf" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 76 | [text_font_sdf](text/text_font_sdf.c) | <img src="text/text_font_sdf.png" alt="text_font_sdf" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 74 | [text_format_text](text/text_format_text.c) | <img src="text/text_format_text.png" alt="text_format_text" width="80"> | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) | | 77 | [text_format_text](text/text_format_text.c) | <img src="text/text_format_text.png" alt="text_format_text" width="80"> | ⭐️☆☆☆ | 1.1 | 3.0 | [Ray](https://github.com/raysan5) |
| 75 | [text_input_box](text/text_input_box.c) | <img src="text/text_input_box.png" alt="text_input_box" width="80"> | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) | | 78 | [text_input_box](text/text_input_box.c) | <img src="text/text_input_box.png" alt="text_input_box" width="80"> | ⭐️⭐️☆☆ | 1.7 | 3.5 | [Ray](https://github.com/raysan5) |
| 76 | [text_writing_anim](text/text_writing_anim.c) | <img src="text/text_writing_anim.png" alt="text_writing_anim" width="80"> | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) | | 79 | [text_writing_anim](text/text_writing_anim.c) | <img src="text/text_writing_anim.png" alt="text_writing_anim" width="80"> | ⭐️⭐️☆☆ | 1.4 | 1.4 | [Ray](https://github.com/raysan5) |
| 77 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | <img src="text/text_rectangle_bounds.png" alt="text_rectangle_bounds" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | | 80 | [text_rectangle_bounds](text/text_rectangle_bounds.c) | <img src="text/text_rectangle_bounds.png" alt="text_rectangle_bounds" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) |
| 78 | [text_unicode](text/text_unicode.c) | <img src="text/text_unicode.png" alt="text_unicode" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | | 81 | [text_unicode](text/text_unicode.c) | <img src="text/text_unicode.png" alt="text_unicode" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) |
| 79 | [text_draw_3d](text/text_draw_3d.c) | <img src="text/text_draw_3d.png" alt="text_draw_3d" width="80"> | ⭐️⭐️⭐️⭐️ | 3.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) | | 82 | [text_draw_3d](text/text_draw_3d.c) | <img src="text/text_draw_3d.png" alt="text_draw_3d" width="80"> | ⭐️⭐️⭐️⭐️ | 3.5 | **4.0** | [Vlad Adrian](https://github.com/demizdor) |
| 80 | [text_codepoints_loading](text/text_codepoints_loading.c) | <img src="text/text_codepoints_loading.png" alt="text_codepoints_loading" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) | | 83 | [text_codepoints_loading](text/text_codepoints_loading.c) | <img src="text/text_codepoints_loading.png" alt="text_codepoints_loading" width="80"> | ⭐️⭐️⭐️☆ | **4.2** | **4.2** | [Ray](https://github.com/raysan5) |
### category: models ### category: models
@ -134,24 +135,25 @@ Examples using raylib models functionality, including models loading/generation
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 81 | [models_animation](models/models_animation.c) | <img src="models/models_animation.png" alt="models_animation" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [culacant](https://github.com/culacant) | | 84 | [models_animation](models/models_animation.c) | <img src="models/models_animation.png" alt="models_animation" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [culacant](https://github.com/culacant) |
| 82 | [models_billboard](models/models_billboard.c) | <img src="models/models_billboard.png" alt="models_billboard" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | | 85 | [models_billboard](models/models_billboard.c) | <img src="models/models_billboard.png" alt="models_billboard" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) |
| 83 | [models_box_collisions](models/models_box_collisions.c) | <img src="models/models_box_collisions.png" alt="models_box_collisions" width="80"> | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) | | 86 | [models_box_collisions](models/models_box_collisions.c) | <img src="models/models_box_collisions.png" alt="models_box_collisions" width="80"> | ⭐️☆☆☆ | 1.3 | 3.5 | [Ray](https://github.com/raysan5) |
| 84 | [models_cubicmap](models/models_cubicmap.c) | <img src="models/models_cubicmap.png" alt="models_cubicmap" width="80"> | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | | 87 | [models_cubicmap](models/models_cubicmap.c) | <img src="models/models_cubicmap.png" alt="models_cubicmap" width="80"> | ⭐️⭐️☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) |
| 85 | [models_first_person_maze](models/models_first_person_maze.c) | <img src="models/models_first_person_maze.png" alt="models_first_person_maze" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) | | 88 | [models_first_person_maze](models/models_first_person_maze.c) | <img src="models/models_first_person_maze.png" alt="models_first_person_maze" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 86 | [models_geometric_shapes](models/models_geometric_shapes.c) | <img src="models/models_geometric_shapes.png" alt="models_geometric_shapes" width="80"> | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) | | 89 | [models_geometric_shapes](models/models_geometric_shapes.c) | <img src="models/models_geometric_shapes.png" alt="models_geometric_shapes" width="80"> | ⭐️☆☆☆ | 1.0 | 3.5 | [Ray](https://github.com/raysan5) |
| 87 | [models_mesh_generation](models/models_mesh_generation.c) | <img src="models/models_mesh_generation.png" alt="models_mesh_generation" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | | 90 | [models_mesh_generation](models/models_mesh_generation.c) | <img src="models/models_mesh_generation.png" alt="models_mesh_generation" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) |
| 88 | [models_mesh_picking](models/models_mesh_picking.c) | <img src="models/models_mesh_picking.png" alt="models_mesh_picking" width="80"> | ⭐️⭐️⭐️☆ | 1.7 | **4.0** | [Joel Davis](https://github.com/joeld42) | | 91 | [models_mesh_picking](models/models_mesh_picking.c) | <img src="models/models_mesh_picking.png" alt="models_mesh_picking" width="80"> | ⭐️⭐️⭐️☆ | 1.7 | **4.0** | [Joel Davis](https://github.com/joeld42) |
| 89 | [models_loading](models/models_loading.c) | <img src="models/models_loading.png" alt="models_loading" width="80"> | ⭐️☆☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | | 92 | [models_loading](models/models_loading.c) | <img src="models/models_loading.png" alt="models_loading" width="80"> | ⭐️☆☆☆ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) |
| 90 | [models_loading_gltf](models/models_loading_gltf.c) | <img src="models/models_loading_gltf.png" alt="models_loading_gltf" width="80"> | ⭐️☆☆☆ | 3.7 | **4.2** | [Ray](https://github.com/raysan5) | | 93 | [models_loading_gltf](models/models_loading_gltf.c) | <img src="models/models_loading_gltf.png" alt="models_loading_gltf" width="80"> | ⭐️☆☆☆ | 3.7 | **4.2** | [Ray](https://github.com/raysan5) |
| 91 | [models_loading_vox](models/models_loading_vox.c) | <img src="models/models_loading_vox.png" alt="models_loading_vox" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) | | 94 | [models_loading_vox](models/models_loading_vox.c) | <img src="models/models_loading_vox.png" alt="models_loading_vox" width="80"> | ⭐️☆☆☆ | **4.0** | **4.0** | [Johann Nadalutti](https://github.com/procfxgen) |
| 92 | [models_loading_m3d](models/models_loading_m3d.c) | <img src="models/models_loading_m3d.png" alt="models_loading_m3d" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) | | 95 | [models_loading_m3d](models/models_loading_m3d.c) | <img src="models/models_loading_m3d.png" alt="models_loading_m3d" width="80"> | ⭐️☆☆☆ | **4.2** | **4.2** | [bzt](https://bztsrc.gitlab.io/model3d) |
| 93 | [models_orthographic_projection](models/models_orthographic_projection.c) | <img src="models/models_orthographic_projection.png" alt="models_orthographic_projection" width="80"> | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) | | 96 | [models_orthographic_projection](models/models_orthographic_projection.c) | <img src="models/models_orthographic_projection.png" alt="models_orthographic_projection" width="80"> | ⭐️☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) |
| 94 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | <img src="models/models_rlgl_solar_system.png" alt="models_rlgl_solar_system" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) | | 97 | [models_point_rendering](models/models_point_rendering.c) | <img src="models/models_point_rendering.png" alt="models_point_rendering" width="80"> | ⭐️⭐️☆☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) |
| 95 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | <img src="models/models_yaw_pitch_roll.png" alt="models_yaw_pitch_roll" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) | | 98 | [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | <img src="models/models_rlgl_solar_system.png" alt="models_rlgl_solar_system" width="80"> | ⭐️⭐️⭐️⭐️ | 2.5 | **4.0** | [Ray](https://github.com/raysan5) |
| 96 | [models_waving_cubes](models/models_waving_cubes.c) | <img src="models/models_waving_cubes.png" alt="models_waving_cubes" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) | | 99 | [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | <img src="models/models_yaw_pitch_roll.png" alt="models_yaw_pitch_roll" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Berni](https://github.com/Berni8k) |
| 97 | [models_heightmap](models/models_heightmap.c) | <img src="models/models_heightmap.png" alt="models_heightmap" width="80"> | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) | | 100 | [models_waving_cubes](models/models_waving_cubes.c) | <img src="models/models_waving_cubes.png" alt="models_waving_cubes" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [codecat](https://github.com/codecat) |
| 98 | [models_skybox](models/models_skybox.c) | <img src="models/models_skybox.png" alt="models_skybox" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) | | 101 | [models_heightmap](models/models_heightmap.c) | <img src="models/models_heightmap.png" alt="models_heightmap" width="80"> | ⭐️☆☆☆ | 1.8 | 3.5 | [Ray](https://github.com/raysan5) |
| 102 | [models_skybox](models/models_skybox.c) | <img src="models/models_skybox.png" alt="models_skybox" width="80"> | ⭐️⭐️☆☆ | 1.8 | **4.0** | [Ray](https://github.com/raysan5) |
### category: shaders ### category: shaders
@ -159,26 +161,25 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 99 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | <img src="shaders/shaders_basic_lighting.png" alt="shaders_basic_lighting" width="80"> | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) | | 103 | [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | <img src="shaders/shaders_basic_lighting.png" alt="shaders_basic_lighting" width="80"> | ⭐️⭐️⭐️⭐️ | 3.0 | **4.2** | [Chris Camacho](https://github.com/codifies) |
| 100 | [shaders_model_shader](shaders/shaders_model_shader.c) | <img src="shaders/shaders_model_shader.png" alt="shaders_model_shader" width="80"> | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) | | 104 | [shaders_model_shader](shaders/shaders_model_shader.c) | <img src="shaders/shaders_model_shader.png" alt="shaders_model_shader" width="80"> | ⭐️⭐️☆☆ | 1.3 | 3.7 | [Ray](https://github.com/raysan5) |
| 101 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | <img src="shaders/shaders_shapes_textures.png" alt="shaders_shapes_textures" width="80"> | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) | | 105 | [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | <img src="shaders/shaders_shapes_textures.png" alt="shaders_shapes_textures" width="80"> | ⭐️⭐️☆☆ | 1.7 | 3.7 | [Ray](https://github.com/raysan5) |
| 102 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | <img src="shaders/shaders_custom_uniform.png" alt="shaders_custom_uniform" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 106 | [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | <img src="shaders/shaders_custom_uniform.png" alt="shaders_custom_uniform" width="80"> | ⭐️⭐️☆☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 103 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | <img src="shaders/shaders_postprocessing.png" alt="shaders_postprocessing" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) | | 107 | [shaders_postprocessing](shaders/shaders_postprocessing.c) | <img src="shaders/shaders_postprocessing.png" alt="shaders_postprocessing" width="80"> | ⭐️⭐️⭐️☆ | 1.3 | **4.0** | [Ray](https://github.com/raysan5) |
| 104 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | <img src="shaders/shaders_palette_switch.png" alt="shaders_palette_switch" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) | | 108 | [shaders_palette_switch](shaders/shaders_palette_switch.c) | <img src="shaders/shaders_palette_switch.png" alt="shaders_palette_switch" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) |
| 105 | [shaders_raymarching](shaders/shaders_raymarching.c) | <img src="shaders/shaders_raymarching.png" alt="shaders_raymarching" width="80"> | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) | | 109 | [shaders_raymarching](shaders/shaders_raymarching.c) | <img src="shaders/shaders_raymarching.png" alt="shaders_raymarching" width="80"> | ⭐️⭐️⭐️⭐️ | 2.0 | **4.2** | [Ray](https://github.com/raysan5) |
| 106 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | <img src="shaders/shaders_texture_drawing.png" alt="shaders_texture_drawing" width="80"> | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) | | 110 | [shaders_texture_drawing](shaders/shaders_texture_drawing.c) | <img src="shaders/shaders_texture_drawing.png" alt="shaders_texture_drawing" width="80"> | ⭐️⭐️☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/) |
| 107 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | <img src="shaders/shaders_texture_outline.png" alt="shaders_texture_outline" width="80"> | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) | | 111 | [shaders_texture_outline](shaders/shaders_texture_outline.c) | <img src="shaders/shaders_texture_outline.png" alt="shaders_texture_outline" width="80"> | ⭐️⭐️⭐️☆ | **4.0** | **4.0** | [Samuel Skiff](https://github.com/GoldenThumbs) |
| 108 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | <img src="shaders/shaders_texture_waves.png" alt="shaders_texture_waves" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | | 112 | [shaders_texture_waves](shaders/shaders_texture_waves.c) | <img src="shaders/shaders_texture_waves.png" alt="shaders_texture_waves" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) |
| 109 | [shaders_julia_set](shaders/shaders_julia_set.c) | <img src="shaders/shaders_julia_set.png" alt="shaders_julia_set" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) | | 113 | [shaders_julia_set](shaders/shaders_julia_set.c) | <img src="shaders/shaders_julia_set.png" alt="shaders_julia_set" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [eggmund](https://github.com/eggmund) |
| 110 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | <img src="shaders/shaders_eratosthenes.png" alt="shaders_eratosthenes" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) | | 114 | [shaders_eratosthenes](shaders/shaders_eratosthenes.c) | <img src="shaders/shaders_eratosthenes.png" alt="shaders_eratosthenes" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | **4.0** | [ProfJski](https://github.com/ProfJski) |
| 111 | [shaders_fog](shaders/shaders_fog.c) | <img src="shaders/shaders_fog.png" alt="shaders_fog" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | | 115 | [shaders_fog](shaders/shaders_fog.c) | <img src="shaders/shaders_fog.png" alt="shaders_fog" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
| 112 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | <img src="shaders/shaders_simple_mask.png" alt="shaders_simple_mask" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | | 116 | [shaders_simple_mask](shaders/shaders_simple_mask.c) | <img src="shaders/shaders_simple_mask.png" alt="shaders_simple_mask" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
| 113 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | <img src="shaders/shaders_hot_reloading.png" alt="shaders_hot_reloading" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) | | 117 | [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | <img src="shaders/shaders_hot_reloading.png" alt="shaders_hot_reloading" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.5 | [Ray](https://github.com/raysan5) |
| 114 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | <img src="shaders/shaders_mesh_instancing.png" alt="shaders_mesh_instancing" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) | | 118 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | <img src="shaders/shaders_mesh_instancing.png" alt="shaders_mesh_instancing" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) |
| 115 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) | | 119 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 116 | [shaders_spotlight](shaders/shaders_spotlight.c) | <img src="shaders/shaders_spotlight.png" alt="shaders_spotlight" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) | | 120 | [shaders_spotlight](shaders/shaders_spotlight.c) | <img src="shaders/shaders_spotlight.png" alt="shaders_spotlight" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
| 117 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | <img src="shaders/shaders_deferred_render.png" alt="shaders_deferred_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) | | 121 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | <img src="shaders/shaders_deferred_render.png" alt="shaders_deferred_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
| 118 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | <img src="shaders/shaders_vertex_displacement.png" alt="shaders_deferred_render" width="80"> | ⭐️☆☆☆ | 1.5 | 1.5 | [Alex ZH](https://github.com/ZzzhHe) |
### category: audio ### category: audio
@ -186,10 +187,10 @@ Examples using raylib audio functionality, including sound/music loading and pla
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 119 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) | | 122 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) |
| 120 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) | | 123 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
| 121 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) | | 124 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) |
| 122 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) | | 125 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) |
### category: others ### category: others
@ -197,11 +198,11 @@ Examples showing raylib misc functionality that does not fit in other categories
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------| |----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
| 123 | [rlgl_standalone](others/rlgl_standalone.c) | <img src="others/rlgl_standalone.png" alt="rlgl_standalone" width="80"> | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) | | 126 | [rlgl_standalone](others/rlgl_standalone.c) | <img src="others/rlgl_standalone.png" alt="rlgl_standalone" width="80"> | ⭐️⭐️⭐️⭐️ | 1.6 | **4.0** | [Ray](https://github.com/raysan5) |
| 124 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | <img src="others/rlgl_compute_shader.png" alt="rlgl_compute_shader" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) | | 127 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | <img src="others/rlgl_compute_shader.png" alt="rlgl_compute_shader" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Teddy Astie](https://github.com/tsnake41) |
| 125 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | | 128 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 3.0 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
| 126 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) | | 129 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | **4.0** | **4.0** | [Stephan Soller](https://github.com/arkanis) |
| 127 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | | 130 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with! As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with!

View File

@ -0,0 +1,123 @@
/*******************************************************************************************
*
* raylib [core] example - input virtual controls
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example create by GreenSnakeLinux (@GreenSnakeLinux),
* lighter by oblerion (@oblerion) and
* reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
const int dpadX = 90;
const int dpadY = 300;
const int dpadRad = 25;//radius of each pad
Color dpadColor = BLUE;
int dpadKeydown = -1;//-1 if not down, else 0,1,2,3
const float dpadCollider[4][2]= // collider array with x,y position
{
{dpadX,dpadY-dpadRad*1.5},//up
{dpadX-dpadRad*1.5,dpadY},//left
{dpadX+dpadRad*1.5,dpadY},//right
{dpadX,dpadY+dpadRad*1.5}//down
};
const char dpadLabel[4]="XYBA";//label of Dpad
float playerX=100;
float playerY=100;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//--------------------------------------------------------------------------
dpadKeydown = -1; //reset
float inputX=0;
float inputY=0;
if(GetTouchPointCount()>0)
{//use touch pos
inputX = GetTouchX();
inputY = GetTouchY();
}
else
{//use mouse pos
inputX = GetMouseX();
inputY = GetMouseY();
}
for(int i=0;i<4;i++)
{
//test distance each collider and input < radius
if( fabsf(dpadCollider[i][1]-inputY) + fabsf(dpadCollider[i][0]-inputX) < dpadRad)
{
dpadKeydown = i;
break;
}
}
// move player
switch(dpadKeydown){
case 0: playerY -= 50*GetFrameTime();
break;
case 1: playerX -= 50*GetFrameTime();
break;
case 2: playerX += 50*GetFrameTime();
break;
case 3: playerY += 50*GetFrameTime();
default:;
};
//--------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for(int i=0;i<4;i++)
{
//draw all pad
DrawCircle(dpadCollider[i][0],dpadCollider[i][1],dpadRad,dpadColor);
if(i!=dpadKeydown)
{
//draw label
DrawText(TextSubtext(dpadLabel,i,1),
dpadCollider[i][0]-5,
dpadCollider[i][1]-5,16,BLACK);
}
}
DrawText("Player",playerX,playerY,16,BLACK);
EndDrawing();
//--------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,118 @@
/*******************************************************************************************
*
* raylib [core] example - Doing skinning on the gpu using a vertex shader
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by Daniel Holden (@orangeduck) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024 Daniel Holden (@orangeduck)
*
* Note: Due to limitations in the Apple OpenGL driver, this feature does not work on MacOS
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - GPU skinning");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model characterModel = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
// Load skinning shader
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
characterModel.materials[1].shader = skinningShader;
// Load gltf model animations
int animsCount = 0;
unsigned int animIndex = 0;
unsigned int animCurrentFrame = 0;
ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount);
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Select current animation
if (IsKeyPressed(KEY_T)) animIndex = (animIndex + 1)%animsCount;
else if (IsKeyPressed(KEY_G)) animIndex = (animIndex + animsCount - 1)%animsCount;
// Update model animation
ModelAnimation anim = modelAnimations[animIndex];
animCurrentFrame = (animCurrentFrame + 1)%anim.frameCount;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw character
characterModel.transform = MatrixTranslate(position.x, position.y, position.z);
UpdateModelAnimationBoneMatrices(characterModel, anim, animCurrentFrame);
DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(modelAnimations, animsCount);
UnloadModel(characterModel); // Unload character model and meshes/material
UnloadShader(skinningShader);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -0,0 +1,182 @@
/*******************************************************************************************
*
* raylib example - point rendering
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example contributed by Reese Gallagher (@satchelfrost) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024 Reese Gallagher (@satchelfrost)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: rand()
#include <math.h> // Required for: cos(), sin()
#define MAX_POINTS 10000000 // 10 million
#define MIN_POINTS 1000 // 1 thousand
// Generate mesh using points
Mesh GenMeshPoints(int numPoints);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - point rendering");
Camera camera = {
.position = { 3.0f, 3.0f, 3.0f },
.target = { 0.0f, 0.0f, 0.0f },
.up = { 0.0f, 1.0f, 0.0f },
.fovy = 45.0f,
.projection = CAMERA_PERSPECTIVE
};
Vector3 position = { 0.0f, 0.0f, 0.0f };
bool useDrawModelPoints = true;
bool numPointsChanged = false;
int numPoints = 1000;
Mesh mesh = GenMeshPoints(numPoints);
Model model = LoadModelFromMesh(mesh);
//SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while(!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsKeyPressed(KEY_SPACE)) useDrawModelPoints = !useDrawModelPoints;
if (IsKeyPressed(KEY_UP))
{
numPoints = (numPoints*10 > MAX_POINTS)? MAX_POINTS : numPoints*10;
numPointsChanged = true;
}
if (IsKeyPressed(KEY_DOWN))
{
numPoints = (numPoints/10 < MIN_POINTS)? MIN_POINTS : numPoints/10;
numPointsChanged = true;
}
// Upload a different point cloud size
if (numPointsChanged)
{
UnloadModel(model);
mesh = GenMeshPoints(numPoints);
model = LoadModelFromMesh(mesh);
numPointsChanged = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
// The new method only uploads the points once to the GPU
if (useDrawModelPoints)
{
DrawModelPoints(model, position, 1.0f, WHITE);
}
else
{
// The old method must continually draw the "points" (lines)
for (int i = 0; i < numPoints; i++)
{
Vector3 pos = {
.x = mesh.vertices[i*3 + 0],
.y = mesh.vertices[i*3 + 1],
.z = mesh.vertices[i*3 + 2],
};
Color color = {
.r = mesh.colors[i*4 + 0],
.g = mesh.colors[i*4 + 1],
.b = mesh.colors[i*4 + 2],
.a = mesh.colors[i*4 + 3],
};
DrawPoint3D(pos, color);
}
}
// Draw a unit sphere for reference
DrawSphereWires(position, 1.0f, 10, 10, YELLOW);
EndMode3D();
// Draw UI text
DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE);
DrawText("Up - increase points", 20, 70, 20, WHITE);
DrawText("Down - decrease points", 20, 100, 20, WHITE);
DrawText("Space - drawing function", 20, 130, 20, WHITE);
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN);
else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
// Generate a spherical point cloud
Mesh GenMeshPoints(int numPoints)
{
Mesh mesh = {
.triangleCount = 1,
.vertexCount = numPoints,
.vertices = (float *)MemAlloc(numPoints*3*sizeof(float)),
.colors = (unsigned char*)MemAlloc(numPoints*4*sizeof(unsigned char)),
};
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
for (int i = 0; i < numPoints; i++)
{
float theta = PI*rand()/RAND_MAX;
float phi = 2.0f*PI*rand()/RAND_MAX;
float r = 10.0f*rand()/RAND_MAX;
mesh.vertices[i*3 + 0] = r*sin(theta)*cos(phi);
mesh.vertices[i*3 + 1] = r*sin(theta)*sin(phi);
mesh.vertices[i*3 + 2] = r*cos(theta);
Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f);
mesh.colors[i*4 + 0] = color.r;
mesh.colors[i*4 + 1] = color.g;
mesh.colors[i*4 + 2] = color.b;
mesh.colors[i*4 + 3] = color.a;
}
// Upload mesh data from CPU (RAM) to GPU (VRAM) memory
UploadMesh(&mesh, false);
return mesh;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -0,0 +1,17 @@
#version 100
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Output fragment color
out vec4 finalColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main()
{
vec4 texelColor = texture(texture0, fragTexCoord);
finalColor = texelColor*colDiffuse*fragColor;
}

View File

@ -0,0 +1,34 @@
#version 100
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec4 vertexColor;
in vec4 vertexBoneIds;
in vec4 vertexBoneWeights;
#define MAX_BONE_NUM 128
uniform mat4 boneMatrices[MAX_BONE_NUM];
uniform mat4 mvp;
out vec2 fragTexCoord;
out vec4 fragColor;
void main()
{
int boneIndex0 = int(vertexBoneIds.x);
int boneIndex1 = int(vertexBoneIds.y);
int boneIndex2 = int(vertexBoneIds.z);
int boneIndex3 = int(vertexBoneIds.w);
vec4 skinnedPosition =
vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
gl_Position = mvp * skinnedPosition;
}

View File

@ -0,0 +1,17 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Output fragment color
out vec4 finalColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main()
{
vec4 texelColor = texture(texture0, fragTexCoord);
finalColor = texelColor*colDiffuse*fragColor;
}

View File

@ -0,0 +1,34 @@
#version 330
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec4 vertexColor;
in vec4 vertexBoneIds;
in vec4 vertexBoneWeights;
#define MAX_BONE_NUM 128
uniform mat4 boneMatrices[MAX_BONE_NUM];
uniform mat4 mvp;
out vec2 fragTexCoord;
out vec4 fragColor;
void main()
{
int boneIndex0 = int(vertexBoneIds.x);
int boneIndex1 = int(vertexBoneIds.y);
int boneIndex2 = int(vertexBoneIds.z);
int boneIndex3 = int(vertexBoneIds.w);
vec4 skinnedPosition =
vertexBoneWeights.x * (boneMatrices[boneIndex0] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.y * (boneMatrices[boneIndex1] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.z * (boneMatrices[boneIndex2] * vec4(vertexPosition, 1.0f)) +
vertexBoneWeights.w * (boneMatrices[boneIndex3] * vec4(vertexPosition, 1.0f));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
gl_Position = mvp * skinnedPosition;
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -47,7 +47,7 @@ int main(void)
UnloadImage(cat); // Unload image from RAM UnloadImage(cat); // Unload image from RAM
// Load custom font for frawing on image // Load custom font for drawing on image
Font font = LoadFont("resources/custom_jupiter_crash.png"); Font font = LoadFont("resources/custom_jupiter_crash.png");
// Draw over image using custom font // Draw over image using custom font

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

@ -41,7 +41,7 @@ OPTIONS:
-f, --format <type> : Define output format for parser data. -f, --format <type> : Define output format for parser data.
Supported types: DEFAULT, JSON, XML, LUA Supported types: DEFAULT, JSON, XML, LUA
-d, --define <DEF> : Define functions specifiers (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc.) -d, --define <DEF> : Define functions specifiers (i.e. RLAPI for raylib.h, RMAPI for raymath.h, etc.)
NOTE: If no specifier defined, defaults to: RLAPI NOTE: If no specifier defined, defaults to: RLAPI
-t, --truncate <after> : Define string to truncate input after (i.e. "RLGL IMPLEMENTATION" for rlgl.h) -t, --truncate <after> : Define string to truncate input after (i.e. "RLGL IMPLEMENTATION" for rlgl.h)
@ -56,7 +56,7 @@ EXAMPLES:
> raylib_parser --output raylib_data.info --format XML > raylib_parser --output raylib_data.info --format XML
Process <raylib.h> to generate <raylib_data.info> as XML text data Process <raylib.h> to generate <raylib_data.info> as XML text data
> raylib_parser --input raymath.h --output raymath_data.info --format XML > raylib_parser --input raymath.h --output raymath_data.info --format XML --define RMAPI
Process <raymath.h> to generate <raymath_data.info> as XML text data Process <raymath.h> to generate <raymath_data.info> as XML text data
``` ```

View File

@ -850,12 +850,22 @@
{ {
"type": "unsigned char *", "type": "unsigned char *",
"name": "boneIds", "name": "boneIds",
"description": "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)" "description": "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)"
}, },
{ {
"type": "float *", "type": "float *",
"name": "boneWeights", "name": "boneWeights",
"description": "Vertex bone weight, up to 4 bones influence by vertex (skinning)" "description": "Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)"
},
{
"type": "Matrix *",
"name": "boneMatrices",
"description": "Bones animated transformation matrices"
},
{
"type": "int",
"name": "boneCount",
"description": "Number of bones"
}, },
{ {
"type": "unsigned int", "type": "unsigned int",
@ -2518,6 +2528,21 @@
"name": "SHADER_LOC_MAP_BRDF", "name": "SHADER_LOC_MAP_BRDF",
"value": 25, "value": 25,
"description": "Shader location: sampler2d texture: brdf" "description": "Shader location: sampler2d texture: brdf"
},
{
"name": "SHADER_LOC_VERTEX_BONEIDS",
"value": 26,
"description": "Shader location: vertex attribute: boneIds"
},
{
"name": "SHADER_LOC_VERTEX_BONEWEIGHTS",
"value": 27,
"description": "Shader location: vertex attribute: boneWeights"
},
{
"name": "SHADER_LOC_BONE_MATRICES",
"value": 28,
"description": "Shader location: array of matrices uniform: boneMatrices"
} }
] ]
}, },
@ -3215,12 +3240,12 @@
}, },
{ {
"name": "ToggleFullscreen", "name": "ToggleFullscreen",
"description": "Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)", "description": "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)",
"returnType": "void" "returnType": "void"
}, },
{ {
"name": "ToggleBorderlessWindowed", "name": "ToggleBorderlessWindowed",
"description": "Toggle window state: borderless windowed (only PLATFORM_DESKTOP)", "description": "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)",
"returnType": "void" "returnType": "void"
}, },
{ {
@ -3738,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": [
{ {
@ -4477,6 +4502,17 @@
"description": "Get the directory of the running application (uses static string)", "description": "Get the directory of the running application (uses static string)",
"returnType": "const char *" "returnType": "const char *"
}, },
{
"name": "MakeDirectory",
"description": "Create directories (including full path requested), returns 0 on success",
"returnType": "int",
"params": [
{
"type": "const char *",
"name": "dirPath"
}
]
},
{ {
"name": "ChangeDirectory", "name": "ChangeDirectory",
"description": "Change working directory, return true on success", "description": "Change working directory, return true on success",
@ -4523,7 +4559,7 @@
}, },
{ {
"name": "LoadDirectoryFilesEx", "name": "LoadDirectoryFilesEx",
"description": "Load directory filepaths with extension filtering and recursive directory scan", "description": "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
"returnType": "FilePathList", "returnType": "FilePathList",
"params": [ "params": [
{ {
@ -4655,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",
@ -5150,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"
}, },
{ {
@ -5238,7 +5319,7 @@
}, },
{ {
"name": "DrawPixel", "name": "DrawPixel",
"description": "Draw a pixel", "description": "Draw a pixel using geometry [Can be slow, use with care]",
"returnType": "void", "returnType": "void",
"params": [ "params": [
{ {
@ -5257,7 +5338,7 @@
}, },
{ {
"name": "DrawPixelV", "name": "DrawPixelV",
"description": "Draw a pixel (Vector version)", "description": "Draw a pixel using geometry (Vector version) [Can be slow, use with care]",
"returnType": "void", "returnType": "void",
"params": [ "params": [
{ {
@ -6779,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)",
@ -6872,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": [
{ {
@ -8336,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": [
{ {
@ -8358,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": [
{ {
@ -8780,6 +8842,25 @@
} }
] ]
}, },
{
"name": "ColorLerp",
"description": "Get color lerp interpolation between two colors, factor [0.0f..1.0f]",
"returnType": "Color",
"params": [
{
"type": "Color",
"name": "color1"
},
{
"type": "Color",
"name": "color2"
},
{
"type": "float",
"name": "factor"
}
]
},
{ {
"name": "GetColor", "name": "GetColor",
"description": "Get Color structure from hexadecimal value", "description": "Get Color structure from hexadecimal value",
@ -8862,7 +8943,7 @@
}, },
{ {
"name": "LoadFontEx", "name": "LoadFontEx",
"description": "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont", "description": "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",
"returnType": "Font", "returnType": "Font",
"params": [ "params": [
{ {
@ -8934,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": [
{ {
@ -10226,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": [
{ {
@ -10366,6 +10447,60 @@
} }
] ]
}, },
{
"name": "DrawModelPoints",
"description": "Draw a model as points",
"returnType": "void",
"params": [
{
"type": "Model",
"name": "model"
},
{
"type": "Vector3",
"name": "position"
},
{
"type": "float",
"name": "scale"
},
{
"type": "Color",
"name": "tint"
}
]
},
{
"name": "DrawModelPointsEx",
"description": "Draw a model as points with extended parameters",
"returnType": "void",
"params": [
{
"type": "Model",
"name": "model"
},
{
"type": "Vector3",
"name": "position"
},
{
"type": "Vector3",
"name": "rotationAxis"
},
{
"type": "float",
"name": "rotationAngle"
},
{
"type": "Vector3",
"name": "scale"
},
{
"type": "Color",
"name": "tint"
}
]
},
{ {
"name": "DrawBoundingBox", "name": "DrawBoundingBox",
"description": "Draw bounding box (wires)", "description": "Draw bounding box (wires)",
@ -10859,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": [
{ {
@ -10993,6 +11128,25 @@
} }
] ]
}, },
{
"name": "UpdateModelAnimationBoneMatrices",
"description": "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)",
"returnType": "void",
"params": [
{
"type": "Model",
"name": "model"
},
{
"type": "ModelAnimation",
"name": "anim"
},
{
"type": "int",
"name": "frame"
}
]
},
{ {
"name": "CheckCollisionSpheres", "name": "CheckCollisionSpheres",
"description": "Check collision between two spheres", "description": "Check collision between two spheres",
@ -11215,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": [
{ {
@ -11259,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": [
{ {
@ -11557,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": [
{ {
@ -11746,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

@ -850,12 +850,22 @@ return {
{ {
type = "unsigned char *", type = "unsigned char *",
name = "boneIds", name = "boneIds",
description = "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)" description = "Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)"
}, },
{ {
type = "float *", type = "float *",
name = "boneWeights", name = "boneWeights",
description = "Vertex bone weight, up to 4 bones influence by vertex (skinning)" description = "Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)"
},
{
type = "Matrix *",
name = "boneMatrices",
description = "Bones animated transformation matrices"
},
{
type = "int",
name = "boneCount",
description = "Number of bones"
}, },
{ {
type = "unsigned int", type = "unsigned int",
@ -2518,6 +2528,21 @@ return {
name = "SHADER_LOC_MAP_BRDF", name = "SHADER_LOC_MAP_BRDF",
value = 25, value = 25,
description = "Shader location: sampler2d texture: brdf" description = "Shader location: sampler2d texture: brdf"
},
{
name = "SHADER_LOC_VERTEX_BONEIDS",
value = 26,
description = "Shader location: vertex attribute: boneIds"
},
{
name = "SHADER_LOC_VERTEX_BONEWEIGHTS",
value = 27,
description = "Shader location: vertex attribute: boneWeights"
},
{
name = "SHADER_LOC_BONE_MATRICES",
value = 28,
description = "Shader location: array of matrices uniform: boneMatrices"
} }
} }
}, },
@ -3158,12 +3183,12 @@ return {
}, },
{ {
name = "ToggleFullscreen", name = "ToggleFullscreen",
description = "Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)", description = "Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)",
returnType = "void" returnType = "void"
}, },
{ {
name = "ToggleBorderlessWindowed", name = "ToggleBorderlessWindowed",
description = "Toggle window state: borderless windowed (only PLATFORM_DESKTOP)", description = "Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)",
returnType = "void" returnType = "void"
}, },
{ {
@ -3564,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"}
@ -4042,6 +4067,14 @@ return {
description = "Get the directory of the running application (uses static string)", description = "Get the directory of the running application (uses static string)",
returnType = "const char *" returnType = "const char *"
}, },
{
name = "MakeDirectory",
description = "Create directories (including full path requested), returns 0 on success",
returnType = "int",
params = {
{type = "const char *", name = "dirPath"}
}
},
{ {
name = "ChangeDirectory", name = "ChangeDirectory",
description = "Change working directory, return true on success", description = "Change working directory, return true on success",
@ -4076,7 +4109,7 @@ return {
}, },
{ {
name = "LoadDirectoryFilesEx", name = "LoadDirectoryFilesEx",
description = "Load directory filepaths with extension filtering and recursive directory scan", description = "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
returnType = "FilePathList", returnType = "FilePathList",
params = { params = {
{type = "const char *", name = "basePath"}, {type = "const char *", name = "basePath"},
@ -4157,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",
@ -4517,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"
}, },
{ {
@ -4581,7 +4641,7 @@ return {
}, },
{ {
name = "DrawPixel", name = "DrawPixel",
description = "Draw a pixel", description = "Draw a pixel using geometry [Can be slow, use with care]",
returnType = "void", returnType = "void",
params = { params = {
{type = "int", name = "posX"}, {type = "int", name = "posX"},
@ -4591,7 +4651,7 @@ return {
}, },
{ {
name = "DrawPixelV", name = "DrawPixelV",
description = "Draw a pixel (Vector version)", description = "Draw a pixel using geometry (Vector version) [Can be slow, use with care]",
returnType = "void", returnType = "void",
params = { params = {
{type = "Vector2", name = "position"}, {type = "Vector2", name = "position"},
@ -5306,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)",
@ -5360,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"}
@ -6125,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"}
@ -6141,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"}
@ -6377,6 +6427,16 @@ return {
{type = "Color", name = "tint"} {type = "Color", name = "tint"}
} }
}, },
{
name = "ColorLerp",
description = "Get color lerp interpolation between two colors, factor [0.0f..1.0f]",
returnType = "Color",
params = {
{type = "Color", name = "color1"},
{type = "Color", name = "color2"},
{type = "float", name = "factor"}
}
},
{ {
name = "GetColor", name = "GetColor",
description = "Get Color structure from hexadecimal value", description = "Get Color structure from hexadecimal value",
@ -6429,7 +6489,7 @@ return {
}, },
{ {
name = "LoadFontEx", name = "LoadFontEx",
description = "Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont", description = "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",
returnType = "Font", returnType = "Font",
params = { params = {
{type = "const char *", name = "fileName"}, {type = "const char *", name = "fileName"},
@ -6462,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"}
@ -7142,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"}
@ -7213,6 +7273,30 @@ return {
{type = "Color", name = "tint"} {type = "Color", name = "tint"}
} }
}, },
{
name = "DrawModelPoints",
description = "Draw a model as points",
returnType = "void",
params = {
{type = "Model", name = "model"},
{type = "Vector3", name = "position"},
{type = "float", name = "scale"},
{type = "Color", name = "tint"}
}
},
{
name = "DrawModelPointsEx",
description = "Draw a model as points with extended parameters",
returnType = "void",
params = {
{type = "Model", name = "model"},
{type = "Vector3", name = "position"},
{type = "Vector3", name = "rotationAxis"},
{type = "float", name = "rotationAngle"},
{type = "Vector3", name = "scale"},
{type = "Color", name = "tint"}
}
},
{ {
name = "DrawBoundingBox", name = "DrawBoundingBox",
description = "Draw bounding box (wires)", description = "Draw bounding box (wires)",
@ -7472,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"}
@ -7552,6 +7636,16 @@ return {
{type = "ModelAnimation", name = "anim"} {type = "ModelAnimation", name = "anim"}
} }
}, },
{
name = "UpdateModelAnimationBoneMatrices",
description = "Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)",
returnType = "void",
params = {
{type = "Model", name = "model"},
{type = "ModelAnimation", name = "anim"},
{type = "int", name = "frame"}
}
},
{ {
name = "CheckCollisionSpheres", name = "CheckCollisionSpheres",
description = "Check collision between two spheres", description = "Check collision between two spheres",
@ -7681,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"}
@ -7713,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"}
@ -7903,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"}
@ -8029,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

@ -160,7 +160,7 @@
<Field type="float" name="rotation" desc="Camera rotation in degrees" /> <Field type="float" name="rotation" desc="Camera rotation in degrees" />
<Field type="float" name="zoom" desc="Camera zoom (scaling), should be 1.0f by default" /> <Field type="float" name="zoom" desc="Camera zoom (scaling), should be 1.0f by default" />
</Struct> </Struct>
<Struct name="Mesh" fieldCount="15" desc="Mesh, vertex data and vao/vbo"> <Struct name="Mesh" fieldCount="17" desc="Mesh, vertex data and vao/vbo">
<Field type="int" name="vertexCount" desc="Number of vertices stored in arrays" /> <Field type="int" name="vertexCount" desc="Number of vertices stored in arrays" />
<Field type="int" name="triangleCount" desc="Number of triangles stored (indexed or not)" /> <Field type="int" name="triangleCount" desc="Number of triangles stored (indexed or not)" />
<Field type="float *" name="vertices" desc="Vertex position (XYZ - 3 components per vertex) (shader-location = 0)" /> <Field type="float *" name="vertices" desc="Vertex position (XYZ - 3 components per vertex) (shader-location = 0)" />
@ -172,8 +172,10 @@
<Field type="unsigned short *" name="indices" desc="Vertex indices (in case vertex data comes indexed)" /> <Field type="unsigned short *" name="indices" desc="Vertex indices (in case vertex data comes indexed)" />
<Field type="float *" name="animVertices" desc="Animated vertex positions (after bones transformations)" /> <Field type="float *" name="animVertices" desc="Animated vertex positions (after bones transformations)" />
<Field type="float *" name="animNormals" desc="Animated normals (after bones transformations)" /> <Field type="float *" name="animNormals" desc="Animated normals (after bones transformations)" />
<Field type="unsigned char *" name="boneIds" desc="Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)" /> <Field type="unsigned char *" name="boneIds" desc="Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)" />
<Field type="float *" name="boneWeights" desc="Vertex bone weight, up to 4 bones influence by vertex (skinning)" /> <Field type="float *" name="boneWeights" desc="Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)" />
<Field type="Matrix *" name="boneMatrices" desc="Bones animated transformation matrices" />
<Field type="int" name="boneCount" desc="Number of bones" />
<Field type="unsigned int" name="vaoId" desc="OpenGL Vertex Array Object id" /> <Field type="unsigned int" name="vaoId" desc="OpenGL Vertex Array Object id" />
<Field type="unsigned int *" name="vboId" desc="OpenGL Vertex Buffer Objects id (default vertex data)" /> <Field type="unsigned int *" name="vboId" desc="OpenGL Vertex Buffer Objects id (default vertex data)" />
</Struct> </Struct>
@ -505,7 +507,7 @@
<Value name="MATERIAL_MAP_PREFILTER" integer="9" desc="Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)" /> <Value name="MATERIAL_MAP_PREFILTER" integer="9" desc="Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)" />
<Value name="MATERIAL_MAP_BRDF" integer="10" desc="Brdf material" /> <Value name="MATERIAL_MAP_BRDF" integer="10" desc="Brdf material" />
</Enum> </Enum>
<Enum name="ShaderLocationIndex" valueCount="26" desc="Shader location index"> <Enum name="ShaderLocationIndex" valueCount="29" desc="Shader location index">
<Value name="SHADER_LOC_VERTEX_POSITION" integer="0" desc="Shader location: vertex attribute: position" /> <Value name="SHADER_LOC_VERTEX_POSITION" integer="0" desc="Shader location: vertex attribute: position" />
<Value name="SHADER_LOC_VERTEX_TEXCOORD01" integer="1" desc="Shader location: vertex attribute: texcoord01" /> <Value name="SHADER_LOC_VERTEX_TEXCOORD01" integer="1" desc="Shader location: vertex attribute: texcoord01" />
<Value name="SHADER_LOC_VERTEX_TEXCOORD02" integer="2" desc="Shader location: vertex attribute: texcoord02" /> <Value name="SHADER_LOC_VERTEX_TEXCOORD02" integer="2" desc="Shader location: vertex attribute: texcoord02" />
@ -532,6 +534,9 @@
<Value name="SHADER_LOC_MAP_IRRADIANCE" integer="23" desc="Shader location: samplerCube texture: irradiance" /> <Value name="SHADER_LOC_MAP_IRRADIANCE" integer="23" desc="Shader location: samplerCube texture: irradiance" />
<Value name="SHADER_LOC_MAP_PREFILTER" integer="24" desc="Shader location: samplerCube texture: prefilter" /> <Value name="SHADER_LOC_MAP_PREFILTER" integer="24" desc="Shader location: samplerCube texture: prefilter" />
<Value name="SHADER_LOC_MAP_BRDF" integer="25" desc="Shader location: sampler2d texture: brdf" /> <Value name="SHADER_LOC_MAP_BRDF" integer="25" desc="Shader location: sampler2d texture: brdf" />
<Value name="SHADER_LOC_VERTEX_BONEIDS" integer="26" desc="Shader location: vertex attribute: boneIds" />
<Value name="SHADER_LOC_VERTEX_BONEWEIGHTS" integer="27" desc="Shader location: vertex attribute: boneWeights" />
<Value name="SHADER_LOC_BONE_MATRICES" integer="28" desc="Shader location: array of matrices uniform: boneMatrices" />
</Enum> </Enum>
<Enum name="ShaderUniformDataType" valueCount="9" desc="Shader uniform data type"> <Enum name="ShaderUniformDataType" valueCount="9" desc="Shader uniform data type">
<Value name="SHADER_UNIFORM_FLOAT" integer="0" desc="Shader uniform type: float" /> <Value name="SHADER_UNIFORM_FLOAT" integer="0" desc="Shader uniform type: float" />
@ -670,7 +675,7 @@
<Param type="unsigned int" name="frames" desc="" /> <Param type="unsigned int" name="frames" desc="" />
</Callback> </Callback>
</Callbacks> </Callbacks>
<Functions count="573"> <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="" />
@ -703,9 +708,9 @@
<Function name="ClearWindowState" retType="void" paramCount="1" desc="Clear window configuration state flags"> <Function name="ClearWindowState" retType="void" paramCount="1" desc="Clear window configuration state flags">
<Param type="unsigned int" name="flags" desc="" /> <Param type="unsigned int" name="flags" desc="" />
</Function> </Function>
<Function name="ToggleFullscreen" retType="void" paramCount="0" desc="Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)"> <Function name="ToggleFullscreen" retType="void" paramCount="0" desc="Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)">
</Function> </Function>
<Function name="ToggleBorderlessWindowed" retType="void" paramCount="0" desc="Toggle window state: borderless windowed (only PLATFORM_DESKTOP)"> <Function name="ToggleBorderlessWindowed" retType="void" paramCount="0" desc="Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)">
</Function> </Function>
<Function name="MaximizeWindow" retType="void" paramCount="0" desc="Set window state: maximized, if resizable (only PLATFORM_DESKTOP)"> <Function name="MaximizeWindow" retType="void" paramCount="0" desc="Set window state: maximized, if resizable (only PLATFORM_DESKTOP)">
</Function> </Function>
@ -866,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">
@ -1069,6 +1074,9 @@
</Function> </Function>
<Function name="GetApplicationDirectory" retType="const char *" paramCount="0" desc="Get the directory of the running application (uses static string)"> <Function name="GetApplicationDirectory" retType="const char *" paramCount="0" desc="Get the directory of the running application (uses static string)">
</Function> </Function>
<Function name="MakeDirectory" retType="int" paramCount="1" desc="Create directories (including full path requested), returns 0 on success">
<Param type="const char *" name="dirPath" desc="" />
</Function>
<Function name="ChangeDirectory" retType="bool" paramCount="1" desc="Change working directory, return true on success"> <Function name="ChangeDirectory" retType="bool" paramCount="1" desc="Change working directory, return true on success">
<Param type="const char *" name="dir" desc="" /> <Param type="const char *" name="dir" desc="" />
</Function> </Function>
@ -1081,7 +1089,7 @@
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths"> <Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths">
<Param type="const char *" name="dirPath" desc="" /> <Param type="const char *" name="dirPath" desc="" />
</Function> </Function>
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and recursive directory scan"> <Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
<Param type="const char *" name="basePath" desc="" /> <Param type="const char *" name="basePath" desc="" />
<Param type="const char *" name="filter" desc="" /> <Param type="const char *" name="filter" desc="" />
<Param type="bool" name="scanSubdirs" desc="" /> <Param type="bool" name="scanSubdirs" desc="" />
@ -1118,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>
@ -1261,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>
@ -1289,12 +1309,12 @@
</Function> </Function>
<Function name="GetShapesTextureRectangle" retType="Rectangle" paramCount="0" desc="Get texture source rectangle that is used for shapes drawing"> <Function name="GetShapesTextureRectangle" retType="Rectangle" paramCount="0" desc="Get texture source rectangle that is used for shapes drawing">
</Function> </Function>
<Function name="DrawPixel" retType="void" paramCount="3" desc="Draw a pixel"> <Function name="DrawPixel" retType="void" paramCount="3" desc="Draw a pixel using geometry [Can be slow, use with care]">
<Param type="int" name="posX" desc="" /> <Param type="int" name="posX" desc="" />
<Param type="int" name="posY" desc="" /> <Param type="int" name="posY" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawPixelV" retType="void" paramCount="2" desc="Draw a pixel (Vector version)"> <Function name="DrawPixelV" retType="void" paramCount="2" desc="Draw a pixel using geometry (Vector version) [Can be slow, use with care]">
<Param type="Vector2" name="position" desc="" /> <Param type="Vector2" name="position" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
@ -1691,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="" />
@ -1716,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)">
@ -2101,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)">
@ -2219,6 +2234,11 @@
<Param type="Color" name="src" desc="" /> <Param type="Color" name="src" desc="" />
<Param type="Color" name="tint" desc="" /> <Param type="Color" name="tint" desc="" />
</Function> </Function>
<Function name="ColorLerp" retType="Color" paramCount="3" desc="Get color lerp interpolation between two colors, factor [0.0f..1.0f]">
<Param type="Color" name="color1" desc="" />
<Param type="Color" name="color2" desc="" />
<Param type="float" name="factor" desc="" />
</Function>
<Function name="GetColor" retType="Color" paramCount="1" desc="Get Color structure from hexadecimal value"> <Function name="GetColor" retType="Color" paramCount="1" desc="Get Color structure from hexadecimal value">
<Param type="unsigned int" name="hexValue" desc="" /> <Param type="unsigned int" name="hexValue" desc="" />
</Function> </Function>
@ -2241,7 +2261,7 @@
<Function name="LoadFont" retType="Font" paramCount="1" desc="Load font from file into GPU memory (VRAM)"> <Function name="LoadFont" retType="Font" paramCount="1" desc="Load font from file into GPU memory (VRAM)">
<Param type="const char *" name="fileName" desc="" /> <Param type="const char *" name="fileName" desc="" />
</Function> </Function>
<Function name="LoadFontEx" retType="Font" paramCount="4" desc="Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character setFont"> <Function name="LoadFontEx" retType="Font" paramCount="4" desc="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">
<Param type="const char *" name="fileName" desc="" /> <Param type="const char *" name="fileName" desc="" />
<Param type="int" name="fontSize" desc="" /> <Param type="int" name="fontSize" desc="" />
<Param type="int *" name="codepoints" desc="" /> <Param type="int *" name="codepoints" desc="" />
@ -2260,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">
@ -2600,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)">
@ -2637,6 +2657,20 @@
<Param type="Vector3" name="scale" desc="" /> <Param type="Vector3" name="scale" desc="" />
<Param type="Color" name="tint" desc="" /> <Param type="Color" name="tint" desc="" />
</Function> </Function>
<Function name="DrawModelPoints" retType="void" paramCount="4" desc="Draw a model as points">
<Param type="Model" name="model" desc="" />
<Param type="Vector3" name="position" desc="" />
<Param type="float" name="scale" desc="" />
<Param type="Color" name="tint" desc="" />
</Function>
<Function name="DrawModelPointsEx" retType="void" paramCount="6" desc="Draw a model as points with extended parameters">
<Param type="Model" name="model" desc="" />
<Param type="Vector3" name="position" desc="" />
<Param type="Vector3" name="rotationAxis" desc="" />
<Param type="float" name="rotationAngle" desc="" />
<Param type="Vector3" name="scale" desc="" />
<Param type="Color" name="tint" desc="" />
</Function>
<Function name="DrawBoundingBox" retType="void" paramCount="2" desc="Draw bounding box (wires)"> <Function name="DrawBoundingBox" retType="void" paramCount="2" desc="Draw bounding box (wires)">
<Param type="BoundingBox" name="box" desc="" /> <Param type="BoundingBox" name="box" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
@ -2767,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)">
@ -2803,6 +2837,11 @@
<Param type="Model" name="model" desc="" /> <Param type="Model" name="model" desc="" />
<Param type="ModelAnimation" name="anim" desc="" /> <Param type="ModelAnimation" name="anim" desc="" />
</Function> </Function>
<Function name="UpdateModelAnimationBoneMatrices" retType="void" paramCount="3" desc="Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)">
<Param type="Model" name="model" desc="" />
<Param type="ModelAnimation" name="anim" desc="" />
<Param type="int" name="frame" desc="" />
</Function>
<Function name="CheckCollisionSpheres" retType="bool" paramCount="4" desc="Check collision between two spheres"> <Function name="CheckCollisionSpheres" retType="bool" paramCount="4" desc="Check collision between two spheres">
<Param type="Vector3" name="center1" desc="" /> <Param type="Vector3" name="center1" desc="" />
<Param type="float" name="radius1" desc="" /> <Param type="float" name="radius1" desc="" />
@ -2864,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">
@ -2876,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">
@ -2956,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">
@ -3007,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

@ -72,7 +72,7 @@
#define MAX_CALLBACKS_TO_PARSE 64 // Maximum number of callbacks to parse #define MAX_CALLBACKS_TO_PARSE 64 // Maximum number of callbacks to parse
#define MAX_FUNCS_TO_PARSE 1024 // Maximum number of functions to parse #define MAX_FUNCS_TO_PARSE 1024 // Maximum number of functions to parse
#define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments) #define MAX_LINE_LENGTH 1024 // Maximum length of one line (including comments)
#define MAX_STRUCT_FIELDS 64 // Maximum number of struct fields #define MAX_STRUCT_FIELDS 64 // Maximum number of struct fields
#define MAX_ENUM_VALUES 512 // Maximum number of enum values #define MAX_ENUM_VALUES 512 // Maximum number of enum values
@ -139,7 +139,7 @@ typedef struct EnumInfo {
// Function info data // Function info data
typedef struct FunctionInfo { typedef struct FunctionInfo {
char name[64]; // Function name char name[64]; // Function name
char desc[128]; // Function description (comment at the end) char desc[512]; // Function description (comment at the end)
char retType[32]; // Return value type char retType[32]; // Return value type
int paramCount; // Number of function parameters int paramCount; // Number of function parameters
char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type

View File

@ -30,8 +30,8 @@ target_link_libraries(${PROJECT_NAME} raylib)
# Web Configurations # Web Configurations
if (${PLATFORM} STREQUAL "Web") if (${PLATFORM} STREQUAL "Web")
# Tell Emscripten to build an example.html file. set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file.
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1")
endif() endif()
# Checks if OSX and links appropriate frameworks (Only required on MacOS) # Checks if OSX and links appropriate frameworks (Only required on MacOS)

View File

@ -22,6 +22,6 @@ Compiling for the web requires the [Emscripten SDK](https://emscripten.org/docs/
``` bash ``` bash
mkdir build mkdir build
cd build cd build
emcmake cmake .. -DPLATFORM=Web -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS="-s USE_GLFW=3" -DCMAKE_EXECUTABLE_SUFFIX=".html" emcmake cmake .. -DPLATFORM=Web -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXECUTABLE_SUFFIX=".html"
emmake make emmake make
``` ```

View File

@ -0,0 +1,387 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug.DLL|Win32">
<Configuration>Debug.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug.DLL|x64">
<Configuration>Debug.DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release.DLL|Win32">
<Configuration>Release.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release.DLL|x64">
<Configuration>Release.DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8245DAD9-D402-4D5C-8F45-32229CD3B263}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>models_loading</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>models_gpu_skinning</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
<Message>Copy Debug DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
<Message>Copy Debug DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy Release DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy Release DLL to output directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\examples\models\models_gpu_skinning.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\raylib\raylib.vcxproj">
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -293,12 +293,12 @@ 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}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_gpu_skinning", "examples\models_gpu_skinning.vcxproj", "{8245DAD9-D402-4D5C-8F45-32229CD3B263}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|x64 = Debug.DLL|x64 Debug.DLL|x64 = Debug.DLL|x64
@ -2531,6 +2531,22 @@ Global
{703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x64.Build.0 = Release|x64 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x64.Build.0 = Release|x64
{703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.ActiveCfg = Release|Win32 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.ActiveCfg = Release|Win32
{703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.Build.0 = Release|Win32 {703BE7BA-5B99-4F70-806D-3A259F6A991E}.Release|x86.Build.0 = Release|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x64.ActiveCfg = Debug|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x64.Build.0 = Debug|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x86.ActiveCfg = Debug|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Debug|x86.Build.0 = Debug|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x64.Build.0 = Release.DLL|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x64.ActiveCfg = Release|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x64.Build.0 = Release|x64
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.ActiveCfg = Release|Win32
{8245DAD9-D402-4D5C-8F45-32229CD3B263}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -2682,6 +2698,7 @@ Global
{D8026C60-CCBC-45DF-9085-BF21569EB414} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE} {D8026C60-CCBC-45DF-9085-BF21569EB414} = {DA049009-21FF-4AC0-84E4-830DD1BCD0CE}
{DF25E545-00FF-4E64-844C-7DF98991F901} = {278D8859-20B1-428F-8448-064F46E1F021} {DF25E545-00FF-4E64-844C-7DF98991F901} = {278D8859-20B1-428F-8448-064F46E1F021}
{703BE7BA-5B99-4F70-806D-3A259F6A991E} = {278D8859-20B1-428F-8448-064F46E1F021} {703BE7BA-5B99-4F70-806D-3A259F6A991E} = {278D8859-20B1-428F-8448-064F46E1F021}
{8245DAD9-D402-4D5C-8F45-32229CD3B263} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

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,377 +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 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;
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, " ").?]; // 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");
raylib.defineCMacro("PLATFORM_DESKTOP", null);
},
.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");
}
raylib.defineCMacro("PLATFORM_DESKTOP", null);
} 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");
raylib.defineCMacro("PLATFORM_DESKTOP", null);
},
.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");
raylib.defineCMacro("PLATFORM_DESKTOP", null);
},
.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_drm: bool = false,
shared: bool = false,
linux_display_backend: LinuxDisplayBackend = .Both,
opengl_version: OpenglVersion = .auto,
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 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_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm,
.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

@ -119,6 +119,16 @@
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#define RL_SUPPORT_MESH_GPU_SKINNING // Remove this if your GPU does not support more than 8 VBOs
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif
// Default shader vertex attribute names to set location points // Default shader vertex attribute names to set location points
// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
@ -170,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
@ -225,7 +234,12 @@
// rmodels: Configuration values // rmodels: Configuration values
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
#else
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh #define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
#endif
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Module: raudio - Configuration Flags // Module: raudio - Configuration Flags

243
src/external/RGFW.h vendored
View File

@ -192,7 +192,7 @@
typedef u32 b32; typedef u32 b32;
#endif #endif
#define RGFW_TRUE 1 #define RGFW_TRUE (!(0))
#define RGFW_FALSE 0 #define RGFW_FALSE 0
/* thse OS macros looks better & are standardized */ /* thse OS macros looks better & are standardized */
@ -276,11 +276,6 @@
#endif #endif
#ifdef RGFW_EGL #ifdef RGFW_EGL
#if defined(__APPLE__)
#warning EGL is not supported for Cocoa, switching back to the native opengl api
#undef RGFW_EGL
#endif
#include <EGL/egl.h> #include <EGL/egl.h>
#elif defined(RGFW_OSMESA) #elif defined(RGFW_OSMESA)
#ifndef __APPLE__ #ifndef __APPLE__
@ -611,10 +606,17 @@ typedef struct RGFW_window {
/** * @defgroup Window_management /** * @defgroup Window_management
* @{ */ * @{ */
/*!
* the class name for X11 and WinAPI. apps with the same class will be grouped by the WM
* by default the class name will == the root window's name
*/
RGFWDEF void RGFW_setClassName(char* name);
/*! this has to be set before createWindow is called, else the fulscreen size is used */ /*! this has to be set before createWindow is called, else the fulscreen size is used */
RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */
RGFW_window* RGFW_createWindow( RGFWDEF RGFW_window* RGFW_createWindow(
const char* name, /* name of the window */ const char* name, /* name of the window */
RGFW_rect rect, /* rect of window */ RGFW_rect rect, /* rect of window */
u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ u16 args /* extra arguments (NULL / (u16)0 means no args used)*/
@ -635,7 +637,7 @@ RGFWDEF RGFW_area RGFW_getScreenSize(void);
although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`
*/ */
RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/
/*! /*!
for RGFW_window_eventWait and RGFW_window_checkEvents for RGFW_window_eventWait and RGFW_window_checkEvents
@ -706,7 +708,7 @@ RGFWDEF void RGFW_window_setName(RGFW_window* win,
char* name char* name
); );
void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */
u8* icon /*!< icon bitmap */, u8* icon /*!< icon bitmap */,
RGFW_area a /*!< width and height of the bitmap*/, RGFW_area a /*!< width and height of the bitmap*/,
i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */
@ -1609,9 +1611,6 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
if (args & RGFW_FULLSCREEN) if (args & RGFW_FULLSCREEN)
rect = RGFW_RECT(0, 0, screenR.w, screenR.h); rect = RGFW_RECT(0, 0, screenR.w, screenR.h);
if (args & RGFW_CENTER)
rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h);
/* set and init the new window's data */ /* set and init the new window's data */
win->r = rect; win->r = rect;
win->event.inFocus = 1; win->event.inFocus = 1;
@ -1627,7 +1626,7 @@ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
void RGFW_window_scaleToMonitor(RGFW_window* win) { void RGFW_window_scaleToMonitor(RGFW_window* win) {
RGFW_monitor monitor = RGFW_window_getMonitor(win); RGFW_monitor monitor = RGFW_window_getMonitor(win);
RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h)));
} }
#endif #endif
@ -1637,6 +1636,16 @@ RGFW_window* RGFW_root = NULL;
#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ #define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */
#define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */ #define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */
#ifdef RGFW_MACOS
RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer);
RGFWDEF void* RGFW_cocoaGetLayer(void);
#endif
char* RGFW_className = NULL;
void RGFW_setClassName(char* name) {
RGFW_className = name;
}
void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }
RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} };
@ -2073,6 +2082,8 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
#ifdef RGFW_WINDOWS #ifdef RGFW_WINDOWS
win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc); win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);
#elif defined(RGFW_MACOS)
win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0);
#else #else
win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display); win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);
#endif #endif
@ -2104,8 +2115,15 @@ void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
EGLint numConfigs; EGLint numConfigs;
eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs); eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);
#if defined(RGFW_MACOS)
void* layer = RGFW_cocoaGetLayer();
RGFW_window_cocoaSetLayer(win, layer);
win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL);
#else
win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL); win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);
#endif
EGLint attribs[] = { EGLint attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION,
@ -2322,7 +2340,7 @@ Start of Linux / Unix defines
u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor};
/*atoms needed for drag and drop*/ /*atoms needed for drag and drop*/
Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate; Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList;
Atom wm_delete_window = 0; Atom wm_delete_window = 0;
@ -2563,9 +2581,13 @@ Start of Linux / Unix defines
// In your .desktop app, if you set the property // In your .desktop app, if you set the property
// StartupWMClass=RGFW that will assoicate the launcher icon // StartupWMClass=RGFW that will assoicate the launcher icon
// with your application - robrohan // with your application - robrohan
if (RGFW_className == NULL)
RGFW_className = (char*)name;
XClassHint *hint = XAllocClassHint(); XClassHint *hint = XAllocClassHint();
assert(hint != NULL); assert(hint != NULL);
hint->res_class = (char*)"RGFW"; hint->res_class = (char*)RGFW_className;
hint->res_name = (char*)name; // just use the window name as the app name hint->res_name = (char*)name; // just use the window name as the app name
XSetClassHint((Display*) win->src.display, win->src.window, hint); XSetClassHint((Display*) win->src.display, win->src.window, hint);
XFree(hint); XFree(hint);
@ -2609,6 +2631,11 @@ Start of Linux / Unix defines
RGFW_window_scaleToMonitor(win); RGFW_window_scaleToMonitor(win);
#endif #endif
if (args & RGFW_CENTER) {
RGFW_area screenR = RGFW_getScreenSize();
RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
}
if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/
XSizeHints* sh = XAllocSizeHints(); XSizeHints* sh = XAllocSizeHints();
sh->flags = (1L << 4) | (1L << 5); sh->flags = (1L << 4) | (1L << 5);
@ -2646,7 +2673,6 @@ Start of Linux / Unix defines
if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */
win->_winArgs |= RGFW_ALLOW_DND; win->_winArgs |= RGFW_ALLOW_DND;
XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);
XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False); XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);
XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False); XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);
@ -2660,15 +2686,16 @@ Start of Linux / Unix defines
/* actions */ /* actions */
XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False); XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);
XdndActionMove = XInternAtom((Display*) win->src.display, "XdndActionMove", False);
XdndActionLink = XInternAtom((Display*) win->src.display, "XdndActionLink", False); XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False);
XdndActionAsk = XInternAtom((Display*) win->src.display, "XdndActionAsk", False); XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False);
XdndActionPrivate = XInternAtom((Display*) win->src.display, "XdndActionPrivate", False);
const Atom version = 5; XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);
const u8 version = 5;
XChangeProperty((Display*) win->src.display, (Window) win->src.window, XChangeProperty((Display*) win->src.display, (Window) win->src.window,
XdndAware, 4, 32, XdndAware, 4, 32,
PropModeReplace, (u8*) &version, 1); /*!< turns on drag and drop */ PropModeReplace, &version, 1); /*!< turns on drag and drop */
} }
#ifdef RGFW_EGL #ifdef RGFW_EGL
@ -2716,17 +2743,16 @@ Start of Linux / Unix defines
return RGFWMouse; return RGFWMouse;
} }
typedef struct XDND {
long source, version;
i32 format;
} XDND; /*!< data structure for xdnd events */
XDND xdnd;
int xAxis = 0, yAxis = 0; int xAxis = 0, yAxis = 0;
RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
assert(win != NULL); assert(win != NULL);
static struct {
long source, version;
i32 format;
} xdnd;
if (win->event.type == 0) if (win->event.type == 0)
RGFW_resetKey(); RGFW_resetKey();
@ -2893,13 +2919,16 @@ Start of Linux / Unix defines
win->event.droppedFilesCount = 0; win->event.droppedFilesCount = 0;
/*
much of this event (drag and drop code) is source from glfw
*/
if ((win->_winArgs & RGFW_ALLOW_DND) == 0) if ((win->_winArgs & RGFW_ALLOW_DND) == 0)
break; break;
XEvent reply = { ClientMessage };
reply.xclient.window = xdnd.source;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long) win->src.window;
reply.xclient.data.l[1] = 0;
reply.xclient.data.l[2] = None;
if (E.xclient.message_type == XdndEnter) { if (E.xclient.message_type == XdndEnter) {
unsigned long count; unsigned long count;
Atom* formats; Atom* formats;
@ -2944,27 +2973,10 @@ Start of Linux / Unix defines
formats = real_formats; formats = real_formats;
} }
u32 i; unsigned long i;
for (i = 0; i < (u32)count; i++) { for (i = 0; i < count; i++) {
char* name = XGetAtomName((Display*) win->src.display, formats[i]); if (formats[i] == XtextUriList || formats[i] == XtextPlain) {
char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" };
for (; 1; name++) {
u32 j;
for (j = 0; j < 2; j++) {
if (*links[j] != *name) {
links[j] = (char*) (const char*) "\1";
continue;
}
if (*links[j] == '\0' && *name == '\0')
xdnd.format = formats[i]; xdnd.format = formats[i];
if (*links[j] != '\0' && *links[j] != '\1')
links[j]++;
}
if (*name == '\0')
break; break;
} }
} }
@ -2994,13 +3006,8 @@ Start of Linux / Unix defines
win->event.point.x = xpos; win->event.point.x = xpos;
win->event.point.y = ypos; win->event.point.y = ypos;
XEvent reply = { ClientMessage };
reply.xclient.window = xdnd.source; reply.xclient.window = xdnd.source;
reply.xclient.message_type = XdndStatus; reply.xclient.message_type = XdndStatus;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long) win->src.window;
reply.xclient.data.l[2] = 0;
reply.xclient.data.l[3] = 0;
if (xdnd.format) { if (xdnd.format) {
reply.xclient.data.l[1] = 1; reply.xclient.data.l[1] = 1;
@ -3035,12 +3042,6 @@ Start of Linux / Unix defines
time); time);
} else if (xdnd.version >= 2) { } else if (xdnd.version >= 2) {
XEvent reply = { ClientMessage }; XEvent reply = { ClientMessage };
reply.xclient.window = xdnd.source;
reply.xclient.message_type = XdndFinished;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long) win->src.window;
reply.xclient.data.l[1] = 0;
reply.xclient.data.l[2] = None;
XSendEvent((Display*) win->src.display, xdnd.source, XSendEvent((Display*) win->src.display, xdnd.source,
False, NoEventMask, &reply); False, NoEventMask, &reply);
@ -3125,11 +3126,7 @@ Start of Linux / Unix defines
XFree(data); XFree(data);
if (xdnd.version >= 2) { if (xdnd.version >= 2) {
XEvent reply = { ClientMessage };
reply.xclient.window = xdnd.source;
reply.xclient.message_type = XdndFinished; reply.xclient.message_type = XdndFinished;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long) win->src.window;
reply.xclient.data.l[1] = result; reply.xclient.data.l[1] = result;
reply.xclient.data.l[2] = XdndActionCopy; reply.xclient.data.l[2] = XdndActionCopy;
@ -3520,9 +3517,6 @@ Start of Linux / Unix defines
XEvent reply = { SelectionNotify }; XEvent reply = { SelectionNotify };
reply.xselection.property = 0; reply.xselection.property = 0;
const Atom formats[] = { UTF8_STRING, XA_STRING };
const i32 formatCount = sizeof(formats) / sizeof(formats[0]);
if (request->target == TARGETS) { if (request->target == TARGETS) {
const Atom targets[] = { TARGETS, const Atom targets[] = { TARGETS,
MULTIPLE, MULTIPLE,
@ -3552,15 +3546,7 @@ Start of Linux / Unix defines
unsigned long i; unsigned long i;
for (i = 0; i < (u32)count; i += 2) { for (i = 0; i < (u32)count; i += 2) {
i32 j; if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) {
for (j = 0; j < formatCount; j++) {
if (targets[i] == formats[j])
break;
}
if (j < formatCount)
{
XChangeProperty((Display*) RGFW_root->src.display, XChangeProperty((Display*) RGFW_root->src.display,
request->requestor, request->requestor,
targets[i + 1], targets[i + 1],
@ -3728,31 +3714,53 @@ Start of Linux / Unix defines
Display* display = XOpenDisplay(NULL); Display* display = XOpenDisplay(NULL);
monitor.rect = RGFW_RECT(0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen)); RGFW_area size = RGFW_getScreenSize();
monitor.physW = (monitor.rect.w * 25.4f / 96.f);
monitor.physH = (monitor.rect.h * 25.4f / 96.f);
strncpy(monitor.name, DisplayString(display), 128); monitor.rect = RGFW_RECT(0, 0, size.w, size.h);
monitor.physW = DisplayWidthMM(display, screen);
monitor.physH = DisplayHeightMM(display, screen);
XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen)); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));
XRRCrtcInfo* ci = NULL; XRRCrtcInfo* ci = NULL;
int crtc = 0; int crtc = screen;
if (sr->ncrtc > crtc) { if (sr->ncrtc > crtc) {
ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]); ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);
} }
if (ci == NULL) { if (ci == NULL) {
float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
monitor.scaleX = (float) (dpi_width) / (float) 96;
monitor.scaleY = (float) (dpi_height) / (float) 96;
XRRFreeScreenResources(sr); XRRFreeScreenResources(sr);
XCloseDisplay(display); XCloseDisplay(display);
return monitor; return monitor;
} }
XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]);
monitor.physW = info->mm_width;
monitor.physH = info->mm_height;
monitor.rect.x = ci->x; monitor.rect.x = ci->x;
monitor.rect.y = ci->y; monitor.rect.y = ci->y;
monitor.rect.w = ci->width;
monitor.rect.h = ci->height;
float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
monitor.scaleX = (float) (dpi_width) / (float) 96;
monitor.scaleY = (float) (dpi_height) / (float) 96;
if (monitor.scaleX > 1 && monitor.scaleX < 1.1)
monitor.scaleX = 1;
if (monitor.scaleY > 1 && monitor.scaleY < 1.1)
monitor.scaleY = 1;
XRRFreeCrtcInfo(ci); XRRFreeCrtcInfo(ci);
XRRFreeScreenResources(sr); XRRFreeScreenResources(sr);
@ -4150,9 +4158,6 @@ RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) {
if (win->src.eventLen >= 0) if (win->src.eventLen >= 0)
ev = win->src.events[win->src.eventLen]; ev = win->src.events[win->src.eventLen];
else {
printf("H2\n");
}
return ev; return ev;
} }
@ -4675,6 +4680,10 @@ static const struct wl_callback_listener wl_surface_frame_listener = {
decoration_manager, win->src.xdg_toplevel); decoration_manager, win->src.xdg_toplevel);
} }
if (args & RGFW_CENTER) {
RGFW_area screenR = RGFW_getScreenSize();
RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
}
if (args & RGFW_OPENGL_SOFTWARE) if (args & RGFW_OPENGL_SOFTWARE)
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
@ -5007,6 +5016,10 @@ static const struct wl_callback_listener wl_surface_frame_listener = {
#include <shellapi.h> #include <shellapi.h>
#include <shellscalingapi.h> #include <shellscalingapi.h>
#include <winuser.h>
__declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
#ifndef RGFW_NO_XINPUT #ifndef RGFW_NO_XINPUT
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
PFN_XInputGetState XInputGetStateSRC = NULL; PFN_XInputGetState XInputGetStateSRC = NULL;
@ -5224,13 +5237,14 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
} }
void RGFW_releaseCursor(RGFW_window* win) { void RGFW_releaseCursor(RGFW_window* win) {
RGFW_UNUSED(win);
ClipCursor(NULL); ClipCursor(NULL);
const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };
RegisterRawInputDevices(&id, 1, sizeof(id)); RegisterRawInputDevices(&id, 1, sizeof(id));
} }
void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) {
RGFW_UNUSED(win) RGFW_UNUSED(win); RGFW_UNUSED(rect);
RECT clipRect; RECT clipRect;
GetClientRect(win->src.window, &clipRect); GetClientRect(win->src.window, &clipRect);
@ -5252,6 +5266,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
if (RGFW_Shcore_dll == NULL) { if (RGFW_Shcore_dll == NULL) {
RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); RGFW_Shcore_dll = LoadLibraryA("shcore.dll");
GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");
SetProcessDPIAware();
} }
#endif #endif
@ -5286,7 +5301,10 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
WNDCLASSA Class = { }; WNDCLASSA Class = { };
#endif #endif
Class.lpszClassName = name; if (RGFW_className == NULL)
RGFW_className = (char*)name;
Class.lpszClassName = RGFW_className;
Class.hInstance = inh; Class.hInstance = inh;
Class.hCursor = LoadCursor(NULL, IDC_ARROW); Class.hCursor = LoadCursor(NULL, IDC_ARROW);
Class.lpfnWndProc = WndProc; Class.lpfnWndProc = WndProc;
@ -5500,6 +5518,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
RGFW_window_scaleToMonitor(win); RGFW_window_scaleToMonitor(win);
#endif #endif
if (args & RGFW_CENTER) {
RGFW_area screenR = RGFW_getScreenSize();
RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
}
#ifdef RGFW_EGL #ifdef RGFW_EGL
if ((args & RGFW_NO_INIT_API) == 0) if ((args & RGFW_NO_INIT_API) == 0)
RGFW_createOpenGLContext(win); RGFW_createOpenGLContext(win);
@ -6100,7 +6123,8 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
if (GetDpiForMonitor != NULL) { if (GetDpiForMonitor != NULL) {
u32 x, y; u32 x, y;
GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y); GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y);
monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI; monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;
monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI; monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;
} }
@ -7102,7 +7126,6 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
// printf("File: %s\n", filePath);
strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH);
win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';
} }
@ -7206,6 +7229,16 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
#endif #endif
} }
void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) {
objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer);
}
void* RGFW_cocoaGetLayer(void) {
return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer"));
}
NSPasteboardType const NSPasteboardTypeURL = "public.url"; NSPasteboardType const NSPasteboardTypeURL = "public.url";
NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url";
@ -7261,6 +7294,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
NSString* str = NSString_stringWithUTF8String(name); NSString* str = NSString_stringWithUTF8String(name);
objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
#ifdef RGFW_EGL
if ((args & RGFW_NO_INIT_API) == 0)
RGFW_createOpenGLContext(win);
#endif
#ifdef RGFW_OPENGL #ifdef RGFW_OPENGL
if ((args & RGFW_NO_INIT_API) == 0) { if ((args & RGFW_NO_INIT_API) == 0) {
void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE); void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
@ -7327,6 +7365,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
RGFW_window_scaleToMonitor(win); RGFW_window_scaleToMonitor(win);
#endif #endif
if (args & RGFW_CENTER) {
RGFW_area screenR = RGFW_getScreenSize();
RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
}
if (args & RGFW_HIDE_MOUSE) if (args & RGFW_HIDE_MOUSE)
RGFW_window_showMouse(win, 0); RGFW_window_showMouse(win, 0);
@ -7933,6 +7976,7 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
} }
void RGFW_releaseCursor(RGFW_window* win) { void RGFW_releaseCursor(RGFW_window* win) {
RGFW_UNUSED(win);
CGAssociateMouseAndMouseCursorPosition(1); CGAssociateMouseAndMouseCursorPosition(1);
} }
@ -7992,13 +8036,11 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height); monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);
CGSize screenSizeMM = CGDisplayScreenSize(display); CGSize screenSizeMM = CGDisplayScreenSize(display);
monitor.physW = screenSizeMM.width / 25.4; monitor.physW = screenSizeMM.width;
monitor.physH = screenSizeMM.height / 25.4; monitor.physH = screenSizeMM.height;
monitor.scaleX = (monitor.rect.w / (screenSizeMM.width)) / 2.6; monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25;
monitor.scaleY = (monitor.rect.h / (screenSizeMM.height)) / 2.6; monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25;
snprintf(monitor.name, 128, "%i %i %i", CGDisplayModelNumber(display), CGDisplayVendorNumber(display), CGDisplaySerialNumber(display));
return monitor; return monitor;
} }
@ -8088,6 +8130,8 @@ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
#if defined(RGFW_OPENGL) #if defined(RGFW_OPENGL)
NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222);
#else
RGFW_UNUSED(swapInterval);
#endif #endif
} }
#endif #endif
@ -8873,11 +8917,12 @@ u64 RGFW_getTime(void) {
} }
void RGFW_releaseCursor(RGFW_window* win) { void RGFW_releaseCursor(RGFW_window* win) {
RGFW_UNUSED(win);
emscripten_exit_pointerlock(); emscripten_exit_pointerlock();
} }
void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
RGFW_UNUSED(win) RGFW_UNUSED(win); RGFW_UNUSED(r);
emscripten_request_pointerlock("#canvas", 1); emscripten_request_pointerlock("#canvas", 1);
} }

View File

@ -996,6 +996,7 @@ const char* _glfwDefaultMappings[] =
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,",
#endif // GLFW_BUILD_LINUX_JOYSTICK #endif // GLFW_BUILD_LINUX_JOYSTICK
}; };

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

@ -1130,7 +1130,7 @@ static par_shapes__rule* par_shapes__pick_rule(const char* name,
total += rule->weight; total += rule->weight;
} }
} }
float r = (float) rand() / RAND_MAX; float r = (float) rand() / (float) RAND_MAX;
float t = 0; float t = 0;
for (int i = 0; i < nrules; i++) { for (int i = 0; i < nrules; i++) {
rule = rules + i; rule = rules + i;

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));

File diff suppressed because it is too large Load Diff

View File

@ -74,7 +74,7 @@ typedef struct {
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern CoreData CORE; // Global CORE state context extern CoreData CORE; // Global CORE state context
extern bool isGpuReady; // Flag to note GPU has been initialized successfully
static PlatformData platform = { 0 }; // Platform specific data static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -694,16 +694,16 @@ void PollInputEvents(void)
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system! // NOTE: Allow closing the window in case a configuration change happened.
// The android_main function should be allowed to return to its caller in order for the
// Android OS to relaunch the activity.
if (platform.app->destroyRequested != 0) if (platform.app->destroyRequested != 0)
{ {
//CORE.Window.shouldClose = true; CORE.Window.shouldClose = true;
//ANativeActivity_finish(platform.app->activity);
} }
} }
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -781,7 +781,7 @@ int InitPlatform(void)
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
// NOTE: Never close window, native activity is controlled by the system! // NOTE: It's highly likely destroyRequested will never be non-zero at the start of the activity lifecycle.
//if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true; //if (platform.app->destroyRequested != 0) CORE.Window.shouldClose = true;
} }
} }
@ -812,6 +812,12 @@ void ClosePlatform(void)
eglTerminate(platform.device); eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY; platform.device = EGL_NO_DISPLAY;
} }
// NOTE: Reset global state in case the activity is being relaunched.
if (platform.app->destroyRequested != 0) {
CORE = (CoreData){0};
platform = (PlatformData){0};
}
} }
// Initialize display device and framebuffer // Initialize display device and framebuffer
@ -982,6 +988,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Initialize OpenGL context (states and resources) // Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true;
// Setup default viewport // Setup default viewport
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height // NOTE: It updated CORE.Window.render.width and CORE.Window.render.height

View File

@ -109,6 +109,7 @@ static void ErrorCallback(int error, const char *description);
// Window callbacks events // Window callbacks events
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void WindowPosCallback(GLFWwindow* window, int x, int y); // GLFW3 WindowPos Callback, runs when window is moved
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized
static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus
@ -147,7 +148,7 @@ void ToggleFullscreen(void)
if (!CORE.Window.fullscreen) if (!CORE.Window.fullscreen)
{ {
// Store previous window position (in case we exit fullscreen) // Store previous window position (in case we exit fullscreen)
glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y); CORE.Window.previousPosition = CORE.Window.position;
int monitorCount = 0; int monitorCount = 0;
int monitorIndex = GetCurrentMonitor(); int monitorIndex = GetCurrentMonitor();
@ -179,7 +180,11 @@ void ToggleFullscreen(void)
CORE.Window.fullscreen = false; CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE); glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
// we update the window position right away
CORE.Window.position.x = CORE.Window.previousPosition.x;
CORE.Window.position.y = CORE.Window.previousPosition.y;
} }
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
@ -190,11 +195,11 @@ void ToggleFullscreen(void)
// Toggle borderless windowed mode // Toggle borderless windowed mode
void ToggleBorderlessWindowed(void) void ToggleBorderlessWindowed(void)
{ {
// Leave fullscreen before attempting to set borderless windowed mode and get screen position from it // Leave fullscreen before attempting to set borderless windowed mode
bool wasOnFullscreen = false; bool wasOnFullscreen = false;
if (CORE.Window.fullscreen) if (CORE.Window.fullscreen)
{ {
CORE.Window.previousPosition = CORE.Window.position; // fullscreen already saves the previous position so it does not need to be set here again
ToggleFullscreen(); ToggleFullscreen();
wasOnFullscreen = true; wasOnFullscreen = true;
} }
@ -213,7 +218,7 @@ void ToggleBorderlessWindowed(void)
{ {
// Store screen position and size // Store screen position and size
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y); if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;
CORE.Window.previousScreen = CORE.Window.screen; CORE.Window.previousScreen = CORE.Window.screen;
// Set undecorated and topmost modes and flags // Set undecorated and topmost modes and flags
@ -255,6 +260,9 @@ void ToggleBorderlessWindowed(void)
glfwFocusWindow(platform.handle); glfwFocusWindow(platform.handle);
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE; CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
CORE.Window.position.x = CORE.Window.previousPosition.x;
CORE.Window.position.y = CORE.Window.previousPosition.y;
} }
} }
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor"); else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
@ -592,6 +600,9 @@ void SetWindowTitle(const char *title)
// Set window position on screen (windowed mode) // Set window position on screen (windowed mode)
void SetWindowPosition(int x, int y) void SetWindowPosition(int x, int y)
{ {
// Update CORE.Window.position as well
CORE.Window.position.x = x;
CORE.Window.position.y = y;
glfwSetWindowPos(platform.handle, x, y); glfwSetWindowPos(platform.handle, x, y);
} }
@ -614,8 +625,9 @@ void SetWindowMonitor(int monitor)
{ {
TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
const int screenWidth = CORE.Window.screen.width; // Here the render width has to be used again in case high dpi flag is enabled
const int screenHeight = CORE.Window.screen.height; const int screenWidth = CORE.Window.render.width;
const int screenHeight = CORE.Window.render.height;
int monitorWorkareaX = 0; int monitorWorkareaX = 0;
int monitorWorkareaY = 0; int monitorWorkareaY = 0;
int monitorWorkareaWidth = 0; int monitorWorkareaWidth = 0;
@ -1222,7 +1234,6 @@ void PollInputEvents(void)
glfwSetWindowShouldClose(platform.handle, GLFW_FALSE); glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1435,7 +1446,7 @@ int InitPlatform(void)
} }
} }
TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height); TRACELOG(LOG_INFO, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
// NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
// for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
@ -1569,11 +1580,16 @@ int InitPlatform(void)
int monitorHeight = 0; int monitorHeight = 0;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight); glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2; // 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 posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2; int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;
if (posX < monitorX) posX = monitorX; if (posX < monitorX) posX = monitorX;
if (posY < monitorY) posY = monitorY; if (posY < monitorY) posY = monitorY;
SetWindowPosition(posX, posY); SetWindowPosition(posX, posY);
// Update CORE.Window.position here so it is correct from the start
CORE.Window.position.x = posX;
CORE.Window.position.y = posY;
} }
// Load OpenGL extensions // Load OpenGL extensions
@ -1585,6 +1601,7 @@ int InitPlatform(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Set window callback events // Set window callback events
glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default! glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
glfwSetWindowPosCallback(platform.handle, WindowPosCallback);
glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback); glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback); glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback); glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
@ -1681,7 +1698,12 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
// NOTE: Postprocessing texture is not scaled to new size // NOTE: Postprocessing texture is not scaled to new size
} }
static void WindowPosCallback(GLFWwindow* window, int x, int y)
{
// Set current window position
CORE.Window.position.x = x;
CORE.Window.position.y = y;
}
static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley) static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)
{ {
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f); CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);

View File

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* rcore_desktop_rgfw template - Functions to manage window, graphics device and inputs * rcore_desktop_rgfw - Functions to manage window, graphics device and inputs
* *
* PLATFORM: RGFW * PLATFORM: RGFW
* - Windows (Win32, Win64) * - Windows (Win32, Win64)
@ -69,6 +69,7 @@ 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__)
@ -76,10 +77,6 @@ void CloseWindow(void);
#define Size NSSIZE #define Size NSSIZE
#endif #endif
#if defined(_MSC_VER)
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
#endif
#include "../external/RGFW.h" #include "../external/RGFW.h"
#if defined(__WIN32) || defined(__WIN64) #if defined(__WIN32) || defined(__WIN64)
@ -291,7 +288,6 @@ void SetWindowState(unsigned int flags)
} }
if (flags & FLAG_WINDOW_RESIZABLE) if (flags & FLAG_WINDOW_RESIZABLE)
{ {
printf("%i %i\n", platform.window->r.w, platform.window->r.h);
RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
} }
@ -538,10 +534,8 @@ void *GetWindowHandle(void)
{ {
#ifdef RGFW_WEBASM #ifdef RGFW_WEBASM
return (void*)platform.window->src.ctx; return (void*)platform.window->src.ctx;
#elif !defined(RGFW_WINDOWS)
return (void *)platform.window->src.window;
#else #else
return platform.window->src.hwnd; return (void*)platform.window->src.window;
#endif #endif
} }
@ -692,7 +686,7 @@ void DisableCursor(void)
{ {
RGFW_disableCursor = true; RGFW_disableCursor = true;
RGFW_window_mouseHold(platform.window, RGFW_AREA(CORE.Window.screen.width / 2, CORE.Window.screen.height / 2)); RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
HideCursor(); HideCursor();
} }
@ -876,9 +870,8 @@ void PollInputEvents(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
CORE.Window.resizedLastFrame = false; CORE.Window.resizedLastFrame = false;
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
#define RGFW_HOLD_MOUSE (1L<<2) #define RGFW_HOLD_MOUSE (1L<<2)
#if defined(RGFW_X11) //|| defined(RGFW_MACOS)
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 };
@ -888,11 +881,9 @@ void PollInputEvents(void)
{ {
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
#endif
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])
@ -944,7 +935,7 @@ void PollInputEvents(void)
SetupViewport(platform.window->r.w, platform.window->r.h); SetupViewport(platform.window->r.w, platform.window->r.h);
CORE.Window.screen.width = platform.window->r.w; CORE.Window.screen.width = platform.window->r.w;
CORE.Window.screen.height = platform.window->r.h; CORE.Window.screen.height = platform.window->r.h;
CORE.Window.currentFbo.width = platform.window->r.w;; CORE.Window.currentFbo.width = platform.window->r.w;
CORE.Window.currentFbo.height = platform.window->r.h; CORE.Window.currentFbo.height = platform.window->r.h;
CORE.Window.resizedLastFrame = true; CORE.Window.resizedLastFrame = true;
} break; } break;
@ -1034,15 +1025,8 @@ void PollInputEvents(void)
{ {
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.currentPosition.x += (float)event->point.x;
CORE.Input.Mouse.currentPosition.y += (float)event->point.y;
if (event->point.x)
CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x;
if (event->point.y)
CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y;
CORE.Input.Mouse.currentPosition.x = (float)event->point.x;
CORE.Input.Mouse.currentPosition.y = (float)event->point.y;
} }
else else
{ {
@ -1209,7 +1193,6 @@ void PollInputEvents(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1266,7 +1249,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

@ -57,6 +57,13 @@
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer) #include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#endif #endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#ifndef MAX_CLIPBOARD_BUFFER_LENGTH
#define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText()
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -852,10 +859,22 @@ void SetClipboardText(const char *text)
} }
// Get clipboard text content // Get clipboard text content
// NOTE: returned string must be freed with SDL_free()
const char *GetClipboardText(void) const char *GetClipboardText(void)
{ {
return SDL_GetClipboardText(); static char buffer[MAX_CLIPBOARD_BUFFER_LENGTH] = { 0 };
char *clipboard = SDL_GetClipboardText();
int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard);
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
{
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
sprintf(truncate, "...");
}
SDL_free(clipboard);
return buffer;
} }
// Show mouse cursor // Show mouse cursor
@ -1590,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

@ -206,7 +206,7 @@ static const short linuxToRaylibMap[KEYMAP_SIZE] = {
[BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, [BTN_TL] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
[BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, [BTN_TL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
[BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, [BTN_TR] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,
[BTN_TR2] GAMEPAD_BUTTON_RIGHT_TRIGGER_2, [BTN_TR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,
[BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT, [BTN_SELECT] = GAMEPAD_BUTTON_MIDDLE_LEFT,
[BTN_MODE] = GAMEPAD_BUTTON_MIDDLE, [BTN_MODE] = GAMEPAD_BUTTON_MIDDLE,
[BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT, [BTN_START] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
@ -764,7 +764,9 @@ int InitPlatform(void)
drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]); drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);
TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes); TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);
if ((con->connection == DRM_MODE_CONNECTED) && (con->encoder_id)) // In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected.
// This might be a hardware or software limitation like on Raspberry Pi Zero with composite output.
if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id))
{ {
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected"); TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");
platform.connector = con; platform.connector = con;
@ -1478,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

@ -352,8 +352,10 @@ typedef struct Mesh {
// Animation vertex data // Animation vertex data
float *animVertices; // Animated vertex positions (after bones transformations) float *animVertices; // Animated vertex positions (after bones transformations)
float *animNormals; // Animated normals (after bones transformations) float *animNormals; // Animated normals (after bones transformations)
unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
Matrix *boneMatrices; // Bones animated transformation matrices
int boneCount; // Number of bones
// OpenGL identifiers // OpenGL identifiers
unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vaoId; // OpenGL Vertex Array Object id
@ -790,7 +792,10 @@ typedef enum {
SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices
} ShaderLocationIndex; } ShaderLocationIndex;
#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
@ -968,8 +973,8 @@ RLAPI bool IsWindowResized(void); // Check if wi
RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed [resizes monitor to match window resolution] (only PLATFORM_DESKTOP)
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP) RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed [resizes window to match monitor resolution] (only PLATFORM_DESKTOP)
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
@ -1039,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
@ -1122,11 +1127,12 @@ RLAPI const char *GetDirectoryPath(const char *filePath); // Get full pa
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
@ -1138,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
@ -1205,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
@ -1228,8 +1238,8 @@ RLAPI Texture2D GetShapesTexture(void); // Get t
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
// Basic shapes drawing functions // Basic shapes drawing functions
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care]
RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines)
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
@ -1306,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
@ -1398,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
@ -1431,6 +1440,7 @@ RLAPI Color ColorBrightness(Color color, float factor); // G
RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f
RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
@ -1443,10 +1453,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions // Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
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 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)
@ -1536,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)
@ -1545,6 +1555,8 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
@ -1577,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
@ -1588,6 +1600,7 @@ RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame);
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
RLAPI void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (Note GPU skinning does not work on Mac)
// Collision detection functions // Collision detection functions
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
@ -1614,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
@ -1644,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
@ -1661,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
@ -444,11 +443,17 @@ void UpdateCamera(Camera *camera, int mode)
bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool rotateUp = false; bool rotateUp = false;
// Camera speeds based on frame time
float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();
float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime();
float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime();
float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime();
if (mode == CAMERA_CUSTOM) {} if (mode == CAMERA_CUSTOM) {}
else if (mode == CAMERA_ORBITAL) else if (mode == CAMERA_ORBITAL)
{ {
// Orbital can just orbit // Orbital can just orbit
Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime()); Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed);
Vector3 view = Vector3Subtract(camera->position, camera->target); Vector3 view = Vector3Subtract(camera->position, camera->target);
view = Vector3Transform(view, rotation); view = Vector3Transform(view, rotation);
camera->position = Vector3Add(camera->target, view); camera->position = Vector3Add(camera->target, view);
@ -456,22 +461,22 @@ void UpdateCamera(Camera *camera, int mode)
else else
{ {
// Camera rotation // Camera rotation
if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_UP)) CameraPitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp);
if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget);
if (IsKeyDown(KEY_Q)) CameraRoll(camera, -CAMERA_ROTATION_SPEED); if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed);
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed);
// Camera movement // Camera movement
// Camera pan (for CAMERA_FREE) // Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
{ {
const Vector2 mouseDelta = GetMouseDelta(); const Vector2 mouseDelta = GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane); if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane); if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED); if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED); if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed);
} }
else else
{ {
@ -481,7 +486,6 @@ void UpdateCamera(Camera *camera, int mode)
} }
// Keyboard support // Keyboard support
float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime();
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane);

View File

@ -165,6 +165,10 @@ unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#elif defined(__linux__) #elif defined(__linux__)
#include <unistd.h> #include <unistd.h>
#elif defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <sys/syslimits.h> #include <sys/syslimits.h>
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
@ -187,14 +191,16 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#include <direct.h> // Required for: _getch(), _chdir() #include <io.h> // Required for: _access() [Used in FileExists()]
#include <direct.h> // Required for: _getch(), _chdir(), _mkdir()
#define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir() #define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir()
#define CHDIR _chdir #define CHDIR _chdir
#include <io.h> // Required for: _access() [Used in FileExists()] #define MKDIR(dir) _mkdir(dir)
#else #else
#include <unistd.h> // Required for: getch(), chdir() (POSIX), access() #include <unistd.h> // Required for: getch(), chdir(), mkdir(), access()
#define GETCWD getcwd #define GETCWD getcwd
#define CHDIR chdir #define CHDIR chdir
#define MKDIR(dir) mkdir(dir, 0777)
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -247,6 +253,10 @@ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record #define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
#endif #endif
#ifndef DIRECTORY_FILTER_TAG
#define DIRECTORY_FILTER_TAG "DIR" // Name tag used to request directory inclusion on directory scan
#endif // NOTE: Used in ScanDirectoryFiles(), ScanDirectoryFilesRecursively() and LoadDirectoryFilesEx()
// Flags operation macros // Flags operation macros
#define FLAG_SET(n, f) ((n) |= (f)) #define FLAG_SET(n, f) ((n) |= (f))
#define FLAG_CLEAR(n, f) ((n) &= ~(f)) #define FLAG_CLEAR(n, f) ((n) &= ~(f))
@ -362,6 +372,11 @@ RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported s
CoreData CORE = { 0 }; // Global CORE state context CoreData CORE = { 0 }; // Global CORE state context
// Flag to note GPU acceleration is available,
// referenced from other modules to support GPU data loading
// NOTE: Useful to allow Texture, RenderTexture, Font.texture, Mesh.vaoId/vboId, Shader loading
bool isGpuReady = false;
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
static int screenshotCounter = 0; // Screenshots counter static int screenshotCounter = 0; // Screenshots counter
#endif #endif
@ -563,7 +578,6 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
//void DisableCursor(void) //void DisableCursor(void)
// Initialize window and OpenGL context // Initialize window and OpenGL context
// NOTE: data parameter could be used to pass any kind of required data to the initialization
void InitWindow(int width, int height, const char *title) void InitWindow(int width, int height, const char *title)
{ {
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
@ -637,11 +651,13 @@ void InitWindow(int width, int height, const char *title)
// Initialize rlgl default data (buffers and shaders) // Initialize rlgl default data (buffers and shaders)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
isGpuReady = true; // Flag to note GPU has been initialized successfully
// Setup default viewport // Setup default viewport
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_MODULE_RTEXT)
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font // Load default font
// WARNING: External function: Module required: rtext // WARNING: External function: Module required: rtext
LoadFontDefault(); LoadFontDefault();
@ -660,6 +676,7 @@ void InitWindow(int width, int height, const char *title)
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
} }
#endif #endif
#endif
#else #else
#if defined(SUPPORT_MODULE_RSHAPES) #if defined(SUPPORT_MODULE_RSHAPES)
// Set default texture and rectangle to be used for shapes drawing // Set default texture and rectangle to be used for shapes drawing
@ -1287,6 +1304,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
// vertex color location = 3 // vertex color location = 3
// vertex tangent location = 4 // vertex tangent location = 4
// vertex texcoord2 location = 5 // vertex texcoord2 location = 5
// vertex boneIds location = 6
// vertex boneWeights location = 7
// NOTE: If any location is not found, loc point becomes -1 // NOTE: If any location is not found, loc point becomes -1
@ -1302,6 +1321,8 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
// Get handles to GLSL uniform locations (vertex shader) // Get handles to GLSL uniform locations (vertex shader)
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
@ -1309,6 +1330,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION); shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION);
shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL); shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL);
shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL); shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL);
shader.locs[SHADER_LOC_BONE_MATRICES] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES);
// Get handles to GLSL uniform locations (fragment shader) // Get handles to GLSL uniform locations (fragment shader)
shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);
@ -1320,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),
@ -2153,6 +2175,28 @@ const char *GetApplicationDirectory(void)
appDir[0] = '.'; appDir[0] = '.';
appDir[1] = '/'; appDir[1] = '/';
} }
#elif defined(__FreeBSD__)
size_t size = sizeof(appDir);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
if (sysctl(mib, 4, appDir, &size, NULL, 0) == 0)
{
int len = strlen(appDir);
for (int i = len; i >= 0; --i)
{
if (appDir[i] == '/')
{
appDir[i + 1] = '\0';
break;
}
}
}
else
{
appDir[0] = '.';
appDir[1] = '/';
}
#endif #endif
return appDir; return appDir;
@ -2224,6 +2268,40 @@ void UnloadDirectoryFiles(FilePathList files)
RL_FREE(files.paths); RL_FREE(files.paths);
} }
// Create directories (including full path requested), returns 0 on success
int MakeDirectory(const char *dirPath)
{
if ((dirPath == NULL) || (dirPath[0] == '\0')) return 1; // Path is not valid
if (DirectoryExists(dirPath)) return 0; // Path already exists (is valid)
// Copy path string to avoid modifying original
int len = (int)strlen(dirPath) + 1;
char *pathcpy = (char *)RL_CALLOC(len, 1);
memcpy(pathcpy, dirPath, len);
// Iterate over pathcpy, create each subdirectory as needed
for (int i = 0; (i < len) && (pathcpy[i] != '\0'); i++)
{
if (pathcpy[i] == ':') i++;
else
{
if ((pathcpy[i] == '\\') || (pathcpy[i] == '/'))
{
pathcpy[i] = '\0';
if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);
pathcpy[i] = '/';
}
}
}
// Create final directory
if (!DirectoryExists(pathcpy)) MKDIR(pathcpy);
RL_FREE(pathcpy);
return 0;
}
// Change working directory, returns true on success // Change working directory, returns true on success
bool ChangeDirectory(const char *dir) bool ChangeDirectory(const char *dir)
{ {
@ -2499,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
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -3304,6 +3641,8 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
#endif #endif
if (filter != NULL) if (filter != NULL)
{
if (IsPathFile(path))
{ {
if (IsFileExtension(path, filter)) if (IsFileExtension(path, filter))
{ {
@ -3312,6 +3651,15 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
} }
} }
else else
{
if (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0)
{
strcpy(files->paths[files->count], path);
files->count++;
}
}
}
else
{ {
strcpy(files->paths[files->count], path); strcpy(files->paths[files->count], path);
files->count++; files->count++;
@ -3368,7 +3716,22 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *fi
break; break;
} }
} }
else ScanDirectoryFilesRecursively(path, files, filter); else
{
if ((filter != NULL) && (TextFindIndex(filter, DIRECTORY_FILTER_TAG) >= 0))
{
strcpy(files->paths[files->count], path);
files->count++;
}
if (files->count >= files->capacity)
{
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
break;
}
ScanDirectoryFilesRecursively(path, files, filter);
}
} }
} }

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

View File

@ -68,12 +68,15 @@
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR * #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)))
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
@ -341,6 +344,17 @@
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
#endif
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -527,6 +541,10 @@ typedef enum {
RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
RL_SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
RL_SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
RL_SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
RL_SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
} rlShaderUniformDataType; } rlShaderUniformDataType;
@ -665,7 +683,7 @@ RLAPI void rlDisableScissorTest(void); // Disable scissor test
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnableWireMode(void); // Enable wire mode RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlEnablePointMode(void); // Enable point mode RLAPI void rlEnablePointMode(void); // Enable point mode
RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode
RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI void rlSetLineWidth(float width); // Set the line drawing width
RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width
RLAPI void rlEnableSmoothLines(void); // Enable line aliasing RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
@ -755,6 +773,7 @@ RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName);
RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute
RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices
RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler
RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
@ -973,6 +992,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
@ -992,6 +1017,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#endif #endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES
#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
#endif
#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#endif #endif
@ -1948,6 +1976,7 @@ void rlEnableWireMode(void)
#endif #endif
} }
// Enable point mode
void rlEnablePointMode(void) void rlEnablePointMode(void)
{ {
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
@ -1956,6 +1985,7 @@ void rlEnablePointMode(void)
glEnable(GL_PROGRAM_POINT_SIZE); glEnable(GL_PROGRAM_POINT_SIZE);
#endif #endif
} }
// Disable wire mode // Disable wire mode
void rlDisableWireMode(void) void rlDisableWireMode(void)
{ {
@ -2442,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
{
// Specific check
if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
{ {
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE"); glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
} }
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");
}
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; 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
@ -4143,6 +4195,11 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
#endif
// NOTE: If some attrib name is no found on the shader, it locations becomes -1 // NOTE: If some attrib name is no found on the shader, it locations becomes -1
glLinkProgram(program); glLinkProgram(program);
@ -4234,8 +4291,16 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break;
case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break;
case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break;
#if !defined(GRAPHICS_API_OPENGL_ES2)
case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break;
case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break;
#endif
case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;
default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
// TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()
} }
#endif #endif
} }
@ -4269,6 +4334,14 @@ void rlSetUniformMatrix(int locIndex, Matrix mat)
#endif #endif
} }
// Set shader value uniform matrix
void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glUniformMatrix4fv(locIndex, count, true, (const float*)matrices);
#endif
}
// Set shader value uniform sampler // Set shader value uniform sampler
void rlSetUniformSampler(int locIndex, unsigned int textureId) void rlSetUniformSampler(int locIndex, unsigned int textureId)
{ {
@ -4410,14 +4483,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
// Get SSBO buffer size // Get SSBO buffer size
unsigned int rlGetShaderBufferSize(unsigned int id) unsigned int rlGetShaderBufferSize(unsigned int id)
{ {
GLint64 size = 0;
#if defined(GRAPHICS_API_OPENGL_43) #if defined(GRAPHICS_API_OPENGL_43)
GLint64 size = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
#endif
return (size > 0)? (unsigned int)size : 0; return (size > 0)? (unsigned int)size : 0;
#else
return 0;
#endif
} }
// Read SSBO buffer data (GPU->CPU) // Read SSBO buffer data (GPU->CPU)

View File

@ -130,7 +130,7 @@
#define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported #define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported
#endif #endif
#ifndef MAX_MESH_VERTEX_BUFFERS #ifndef MAX_MESH_VERTEX_BUFFERS
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh #define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -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;
} }
@ -1246,13 +1261,18 @@ void UploadMesh(Mesh *mesh, bool dynamic)
mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
mesh->vaoId = 0; // Vertex Array Object mesh->vaoId = 0; // Vertex Array Object
mesh->vboId[0] = 0; // Vertex buffer: positions mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0; // Vertex buffer: positions
mesh->vboId[1] = 0; // Vertex buffer: texcoords mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0; // Vertex buffer: texcoords
mesh->vboId[2] = 0; // Vertex buffer: normals mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0; // Vertex buffer: normals
mesh->vboId[3] = 0; // Vertex buffer: colors mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = 0; // Vertex buffer: colors
mesh->vboId[4] = 0; // Vertex buffer: tangents mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = 0; // Vertex buffer: tangents
mesh->vboId[5] = 0; // Vertex buffer: texcoords2 mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = 0; // Vertex buffer: texcoords2
mesh->vboId[6] = 0; // Vertex buffer: indices mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = 0; // Vertex buffer: indices
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = 0; // Vertex buffer: boneIds
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = 0; // Vertex buffer: boneWeights
#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();
@ -1262,12 +1282,12 @@ void UploadMesh(Mesh *mesh, bool dynamic)
// Enable vertex attributes: position (shader-location = 0) // Enable vertex attributes: position (shader-location = 0)
void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices; void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;
mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
// Enable vertex attributes: texcoords (shader-location = 1) // Enable vertex attributes: texcoords (shader-location = 1)
mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
@ -1278,7 +1298,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
{ {
// Enable vertex attributes: normals (shader-location = 2) // Enable vertex attributes: normals (shader-location = 2)
void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals; void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;
mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
} }
@ -1294,7 +1314,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
if (mesh->colors != NULL) if (mesh->colors != NULL)
{ {
// Enable vertex attribute: color (shader-location = 3) // Enable vertex attribute: color (shader-location = 3)
mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);
} }
@ -1310,7 +1330,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
if (mesh->tangents != NULL) if (mesh->tangents != NULL)
{ {
// Enable vertex attribute: tangent (shader-location = 4) // Enable vertex attribute: tangent (shader-location = 4)
mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);
} }
@ -1326,7 +1346,7 @@ void UploadMesh(Mesh *mesh, bool dynamic)
if (mesh->texcoords2 != NULL) if (mesh->texcoords2 != NULL)
{ {
// Enable vertex attribute: texcoord2 (shader-location = 5) // Enable vertex attribute: texcoord2 (shader-location = 5)
mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);
} }
@ -1339,9 +1359,43 @@ void UploadMesh(Mesh *mesh, bool dynamic)
rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2); rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);
} }
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
if (mesh->boneIds != NULL)
{
// Enable vertex attribute: boneIds (shader-location = 7)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS] = rlLoadVertexBuffer(mesh->boneIds, mesh->vertexCount*4*sizeof(unsigned char), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
}
else
{
// Default vertex attribute: boneIds
// WARNING: Default value provided to shader if location available
float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, value, SHADER_ATTRIB_VEC4, 4);
rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS);
}
if (mesh->boneWeights != NULL)
{
// Enable vertex attribute: boneWeights (shader-location = 8)
mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS] = rlLoadVertexBuffer(mesh->boneWeights, mesh->vertexCount*4*sizeof(float), dynamic);
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
}
else
{
// Default vertex attribute: boneWeights
// WARNING: Default value provided to shader if location available
float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, value, SHADER_ATTRIB_VEC4, 2);
rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS);
}
#endif
if (mesh->indices != NULL) if (mesh->indices != NULL)
{ {
mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic); mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);
} }
if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);
@ -1451,6 +1505,14 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
// 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
// Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
}
#endif
//----------------------------------------------------- //-----------------------------------------------------
// Bind active texture maps (if available) // Bind active texture maps (if available)
@ -1478,19 +1540,19 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
if (!rlEnableVertexArray(mesh.vaoId)) if (!rlEnableVertexArray(mesh.vaoId))
{ {
// Bind mesh VBO data: vertex position (shader-location = 0) // Bind mesh VBO data: vertex position (shader-location = 0)
rlEnableVertexBuffer(mesh.vboId[0]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
// Bind mesh VBO data: vertex texcoords (shader-location = 1) // Bind mesh VBO data: vertex texcoords (shader-location = 1)
rlEnableVertexBuffer(mesh.vboId[1]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
{ {
// Bind mesh VBO data: vertex normals (shader-location = 2) // Bind mesh VBO data: vertex normals (shader-location = 2)
rlEnableVertexBuffer(mesh.vboId[2]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);
} }
@ -1498,9 +1560,9 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)
{ {
if (mesh.vboId[3] != 0) if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)
{ {
rlEnableVertexBuffer(mesh.vboId[3]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
} }
@ -1517,7 +1579,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[4]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);
} }
@ -1525,12 +1587,30 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[5]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
} }
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)
{
rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
}
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{
rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);
}
#endif
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);
} }
int eyeCount = 1; int eyeCount = 1;
@ -1671,6 +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
// Upload Bone Transforms
if (material.shader.locs[SHADER_LOC_BONE_MATRICES] != -1 && mesh.boneMatrices)
{
rlSetUniformMatrices(material.shader.locs[SHADER_LOC_BONE_MATRICES], mesh.boneMatrices, mesh.boneCount);
}
#endif
//----------------------------------------------------- //-----------------------------------------------------
// Bind active texture maps (if available) // Bind active texture maps (if available)
@ -1696,19 +1785,19 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
if (!rlEnableVertexArray(mesh.vaoId)) if (!rlEnableVertexArray(mesh.vaoId))
{ {
// Bind mesh VBO data: vertex position (shader-location = 0) // Bind mesh VBO data: vertex position (shader-location = 0)
rlEnableVertexBuffer(mesh.vboId[0]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
// Bind mesh VBO data: vertex texcoords (shader-location = 1) // Bind mesh VBO data: vertex texcoords (shader-location = 1)
rlEnableVertexBuffer(mesh.vboId[1]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
{ {
// Bind mesh VBO data: vertex normals (shader-location = 2) // Bind mesh VBO data: vertex normals (shader-location = 2)
rlEnableVertexBuffer(mesh.vboId[2]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);
} }
@ -1716,9 +1805,9 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)
{ {
if (mesh.vboId[3] != 0) if (mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR] != 0)
{ {
rlEnableVertexBuffer(mesh.vboId[3]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
} }
@ -1735,7 +1824,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[4]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);
} }
@ -1743,12 +1832,30 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[5]); rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
} }
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); #ifdef RL_SUPPORT_MESH_GPU_SKINNING
// Bind mesh VBO data: vertex bone ids (shader-location = 6, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEIDS] != -1)
{
rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS], 4, RL_UNSIGNED_BYTE, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEIDS]);
}
// Bind mesh VBO data: vertex bone weights (shader-location = 7, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] != -1)
{
rlEnableVertexBuffer(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS]);
}
#endif
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES]);
} }
int eyeCount = 1; int eyeCount = 1;
@ -1825,6 +1932,7 @@ void UnloadMesh(Mesh mesh)
RL_FREE(mesh.animNormals); RL_FREE(mesh.animNormals);
RL_FREE(mesh.boneWeights); RL_FREE(mesh.boneWeights);
RL_FREE(mesh.boneIds); RL_FREE(mesh.boneIds);
RL_FREE(mesh.boneMatrices);
} }
// Export mesh data to file // Export mesh data to file
@ -2004,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)
@ -2016,6 +2123,8 @@ static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, i
// NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
materials[m] = LoadMaterialDefault(); materials[m] = LoadMaterialDefault();
if (mats == NULL) continue;
// Get default texture, in case no texture is defined // Get default texture, in case no texture is defined
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
@ -2089,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;
} }
@ -2253,6 +2364,50 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
} }
} }
void UpdateModelAnimationBoneMatrices(Model model, ModelAnimation anim, int frame)
{
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
{
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
for (int i = 0; i < model.meshCount; i++)
{
if (model.meshes[i].boneMatrices)
{
assert(model.meshes[i].boneCount == anim.boneCount);
for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
{
Vector3 inTranslation = model.bindPose[boneId].translation;
Quaternion inRotation = model.bindPose[boneId].rotation;
Vector3 inScale = model.bindPose[boneId].scale;
Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
Vector3 outScale = anim.framePoses[frame][boneId].scale;
Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));
Quaternion invRotation = QuaternionInvert(inRotation);
Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
Vector3 boneTranslation = Vector3Add(
Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
outRotation), outTranslation);
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
Vector3 boneScale = Vector3Multiply(outScale, invScale);
Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
QuaternionToMatrix(boneRotation),
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
MatrixScale(boneScale.x, boneScale.y, boneScale.z));
model.meshes[i].boneMatrices[boneId] = boneMatrix;
}
}
}
}
}
// Unload animation array data // Unload animation array data
void UnloadModelAnimations(ModelAnimation *animations, int animCount) void UnloadModelAnimations(ModelAnimation *animations, int animCount)
{ {
@ -3631,6 +3786,30 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
rlDisableWireMode(); rlDisableWireMode();
} }
// Draw a model points
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
{
rlEnablePointMode();
rlDisableBackfaceCulling();
DrawModel(model, position, scale, tint);
rlEnableBackfaceCulling();
rlDisableWireMode();
}
// Draw a model points
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
{
rlEnablePointMode();
rlDisableBackfaceCulling();
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
rlEnableBackfaceCulling();
rlDisableWireMode();
}
// Draw a billboard // Draw a billboard
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
{ {
@ -4049,20 +4228,23 @@ static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform
// - the mesh is automatically triangulated by tinyobj // - the mesh is automatically triangulated by tinyobj
static Model LoadOBJ(const char *fileName) static Model LoadOBJ(const char *fileName)
{ {
tinyobj_attrib_t objAttributes = { 0 };
tinyobj_shape_t* objShapes = NULL;
unsigned int objShapeCount = 0;
tinyobj_material_t* objMaterials = NULL;
unsigned int objMaterialCount = 0;
Model model = { 0 }; Model model = { 0 };
model.transform = MatrixIdentity();
tinyobj_attrib_t attrib = { 0 };
tinyobj_shape_t *meshes = NULL;
unsigned int meshCount = 0;
tinyobj_material_t *materials = NULL;
unsigned int materialCount = 0;
char* fileText = LoadFileText(fileName); char* fileText = LoadFileText(fileName);
if (fileText != NULL) if (fileText == NULL)
{ {
unsigned int dataSize = (unsigned int)strlen(fileText); TRACELOG(LOG_ERROR, "MODEL Unable to read obj file %s", fileName);
return model;
}
char currentDir[1024] = { 0 }; char currentDir[1024] = { 0 };
strcpy(currentDir, GetWorkingDirectory()); // Save current working directory strcpy(currentDir, GetWorkingDirectory()); // Save current working directory
@ -4072,108 +4254,211 @@ static Model LoadOBJ(const char *fileName)
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir); TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
} }
unsigned int dataSize = (unsigned int)strlen(fileText);
unsigned int flags = TINYOBJ_FLAG_TRIANGULATE; unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;
int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileText, dataSize, flags); int ret = tinyobj_parse_obj(&objAttributes, &objShapes, &objShapeCount, &objMaterials, &objMaterialCount, fileText, dataSize, flags);
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName); if (ret != TINYOBJ_SUCCESS)
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
// WARNING: We are not splitting meshes by materials (previous implementation)
// Depending on the provided OBJ that was not the best option and it just crashed
// so, implementation was simplified to prioritize parsed meshes
model.meshCount = meshCount;
// Set number of materials available
// NOTE: There could be more materials available than meshes but it will be resolved at
// model.meshMaterial, just assigning the right material to corresponding mesh
model.materialCount = materialCount;
if (model.materialCount == 0)
{ {
model.materialCount = 1; TRACELOG(LOG_ERROR, "MODEL Unable to read obj data %s", fileName);
TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes"); return model;
} }
else if (model.materialCount > 1 && model.meshCount > 1)
{
// TEMP warning about multiple materials, to be removed when proper splitting code is implemented
// any obj with multiple materials will need to have it's materials assigned by the user in code to work at this time
TRACELOG(LOG_INFO, "MODEL: OBJ has multiple materials, manual material assignment will be required.");
}
// Init model meshes and materials
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
// Process each provided mesh
for (int i = 0; i < model.meshCount; i++)
{
// WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset
// because in case of triangulated quads, meshes[i].length actually report quads,
// despite the triangulation that is efectively considered on attrib.num_faces
unsigned int tris = 0;
if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;
else tris = meshes[i + 1].face_offset;
model.meshes[i].vertexCount = tris*3;
model.meshes[i].triangleCount = tris; // Face count (triangulated)
model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float));
model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshMaterial[i] = 0; // By default, assign material 0 to each mesh
// Process all mesh faces
for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3)
{
// Get indices for the face
tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0];
tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1];
tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2];
// Fill vertices buffer (float) using vertex index of the face
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; }
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; }
for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; }
if (attrib.num_texcoords > 0)
{
// Fill texcoords buffer (float) using vertex index of the face
// NOTE: Y-coordinate must be flipped upside-down
model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];
model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1];
model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];
model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1];
model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];
model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1];
}
if (attrib.num_normals > 0)
{
// Fill normals buffer (float) using vertex index of the face
for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; }
for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; }
for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; }
}
}
}
// Init model materials
if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount);
else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh
tinyobj_attrib_free(&attrib);
tinyobj_shapes_free(meshes, model.meshCount);
tinyobj_materials_free(materials, materialCount);
UnloadFileText(fileText); UnloadFileText(fileText);
unsigned int faceVertIndex = 0;
unsigned int nextShape = 1;
int lastMaterial = -1;
unsigned int meshIndex = 0;
// count meshes
unsigned int nextShapeEnd = objAttributes.num_face_num_verts;
// see how many verts till the next shape
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
// walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{
if (faceVertIndex >= nextShapeEnd)
{
// try to find the last vert in the next shape
nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
meshIndex++;
}
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)
{
meshIndex++;// if this is a new material, we need to allocate a new mesh
}
lastMaterial = objAttributes.material_ids[faceId];
faceVertIndex += objAttributes.face_num_verts[faceId];
}
// allocate the base meshes and materials
model.meshCount = meshIndex + 1;
model.meshes = (Mesh*)MemAlloc(sizeof(Mesh) * model.meshCount);
if (objMaterialCount > 0)
{
model.materialCount = objMaterialCount;
model.materials = (Material*)MemAlloc(sizeof(Material) * objMaterialCount);
}
else // we must allocate at least one material
{
model.materialCount = 1;
model.materials = (Material*)MemAlloc(sizeof(Material) * 1);
}
model.meshMaterial = (int*)MemAlloc(sizeof(int) * model.meshCount);
// see how many verts are in each mesh
unsigned int* localMeshVertexCounts = (unsigned int*)MemAlloc(sizeof(unsigned int) * model.meshCount);
faceVertIndex = 0;
nextShapeEnd = objAttributes.num_face_num_verts;
lastMaterial = -1;
meshIndex = 0;
unsigned int localMeshVertexCount = 0;
nextShape = 1;
if (objShapeCount > 1)
nextShapeEnd = objShapes[nextShape].face_offset;
// walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{
bool newMesh = false; // do we need a new mesh?
if (faceVertIndex >= nextShapeEnd)
{
// try to find the last vert in the next shape
nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
newMesh = true;
}
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)
{
newMesh = true;
}
lastMaterial = objAttributes.material_ids[faceId];
if (newMesh)
{
localMeshVertexCounts[meshIndex] = localMeshVertexCount;
localMeshVertexCount = 0;
meshIndex++;
}
faceVertIndex += objAttributes.face_num_verts[faceId];
localMeshVertexCount += objAttributes.face_num_verts[faceId];
}
localMeshVertexCounts[meshIndex] = localMeshVertexCount;
for (int i = 0; i < model.meshCount; i++)
{
// allocate the buffers for each mesh
unsigned int vertexCount = localMeshVertexCounts[i];
model.meshes[i].vertexCount = vertexCount;
model.meshes[i].triangleCount = vertexCount / 3;
model.meshes[i].vertices = (float*)MemAlloc(sizeof(float) * vertexCount * 3);
model.meshes[i].normals = (float*)MemAlloc(sizeof(float) * vertexCount * 3);
model.meshes[i].texcoords = (float*)MemAlloc(sizeof(float) * vertexCount * 2);
model.meshes[i].colors = (unsigned char*)MemAlloc(sizeof(unsigned char) * vertexCount * 4);
}
MemFree(localMeshVertexCounts);
localMeshVertexCounts = NULL;
// fill meshes
faceVertIndex = 0;
nextShapeEnd = objAttributes.num_face_num_verts;
// see how many verts till the next shape
nextShape = 1;
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
lastMaterial = -1;
meshIndex = 0;
localMeshVertexCount = 0;
// walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{
bool newMesh = false; // do we need a new mesh?
if (faceVertIndex >= nextShapeEnd)
{
// try to find the last vert in the next shape
nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
newMesh = true;
}
// if this is a new material, we need to allocate a new mesh
if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;
lastMaterial = objAttributes.material_ids[faceId];
if (newMesh)
{
localMeshVertexCount = 0;
meshIndex++;
}
int matId = 0;
if (lastMaterial >= 0 && lastMaterial < (int)objMaterialCount)
matId = lastMaterial;
model.meshMaterial[meshIndex] = matId;
for (int f = 0; f < objAttributes.face_num_verts[faceId]; f++)
{
int vertIndex = objAttributes.faces[faceVertIndex].v_idx;
int normalIndex = objAttributes.faces[faceVertIndex].vn_idx;
int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx;
for (int i = 0; i < 3; i++)
model.meshes[meshIndex].vertices[localMeshVertexCount * 3 + i] = objAttributes.vertices[vertIndex * 3 + i];
for (int i = 0; i < 3; i++)
model.meshes[meshIndex].normals[localMeshVertexCount * 3 + i] = objAttributes.normals[normalIndex * 3 + i];
for (int i = 0; i < 2; i++)
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + i] = objAttributes.texcoords[texcordIndex * 2 + i];
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1];
for (int i = 0; i < 4; i++)
model.meshes[meshIndex].colors[localMeshVertexCount * 4 + i] = 255;
faceVertIndex++;
localMeshVertexCount++;
}
}
if (objMaterialCount > 0) ProcessMaterialsOBJ(model.materials, objMaterials, objMaterialCount);
else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh
tinyobj_attrib_free(&objAttributes);
tinyobj_shapes_free(objShapes, objShapeCount);
tinyobj_materials_free(objMaterials, objMaterialCount);
for (int i = 0; i < model.meshCount; i++)
UploadMesh(model.meshes + i, true);
// Restore current working directory // Restore current working directory
if (CHDIR(currentDir) != 0) if (CHDIR(currentDir) != 0)
{ {
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir); TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);
} }
}
return model; return model;
} }
@ -4540,6 +4825,17 @@ 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++)
{
model.meshes[i].boneCount = model.boneCount;
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
for (int j = 0; j < model.meshes[i].boneCount; j++)
{
model.meshes[i].boneMatrices[j] = MatrixIdentity();
}
}
UnloadFileData(fileData); UnloadFileData(fileData);
RL_FREE(imesh); RL_FREE(imesh);
@ -4948,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));\
}\ }\
} }
@ -5399,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
@ -5421,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
@ -5469,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);
@ -5489,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;
@ -5623,6 +5921,15 @@ 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
model.meshes[meshIndex].boneCount = model.boneCount;
model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
{
model.meshes[meshIndex].boneMatrices[j] = MatrixIdentity();
}
meshIndex++; // Move to next mesh meshIndex++; // Move to next mesh
} }
@ -5803,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;
@ -5938,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);
} }
@ -6390,6 +6701,13 @@ 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].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
for (j = 0; j < model.meshes[i].boneCount; j++)
{
model.meshes[i].boneMatrices[j] = MatrixIdentity();
}
} }
} }

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

@ -124,6 +124,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global variables // Global variables
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
extern bool isGpuReady;
#if defined(SUPPORT_DEFAULT_FONT) #if defined(SUPPORT_DEFAULT_FONT)
// Default font provided by raylib // Default font provided by raylib
// NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core] // NOTE: Default font is loaded on InitWindow() and disposed on CloseWindow() [module: core]
@ -252,15 +253,15 @@ extern void LoadFontDefault(void)
counter++; counter++;
} }
defaultFont.texture = LoadTextureFromImage(imFont); if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Allocate space for our characters info data // Allocate space for our characters info data
// NOTE: This memory must be freed at end! --> Done by CloseWindow() // NOTE: This memory must be freed at end! --> Done by CloseWindow()
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo)); defaultFont.glyphs = (GlyphInfo *)RL_CALLOC(defaultFont.glyphCount, sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle)); defaultFont.recs = (Rectangle *)RL_CALLOC(defaultFont.glyphCount, sizeof(Rectangle));
int currentLine = 0; int currentLine = 0;
int currentPosX = charsDivisor; int currentPosX = charsDivisor;
@ -308,7 +309,7 @@ extern void LoadFontDefault(void)
extern void UnloadFontDefault(void) extern void UnloadFontDefault(void)
{ {
for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image); for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);
UnloadTexture(defaultFont.texture); if (isGpuReady) UnloadTexture(defaultFont.texture);
RL_FREE(defaultFont.glyphs); RL_FREE(defaultFont.glyphs);
RL_FREE(defaultFont.recs); RL_FREE(defaultFont.recs);
} }
@ -362,12 +363,15 @@ Font LoadFont(const char *fileName)
UnloadImage(image); UnloadImage(image);
} }
if (isGpuReady)
{
if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
else else
{ {
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance) SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance)
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS); TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
} }
}
return font; return font;
} }
@ -487,7 +491,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}; };
// Set font with all data parsed from image // Set font with all data parsed from image
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture if (isGpuReady) font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
font.glyphCount = index; font.glyphCount = index;
font.glyphPadding = 0; font.glyphPadding = 0;
@ -556,7 +560,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING; font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0); Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
font.texture = LoadTextureFromImage(atlas); if (isGpuReady) font.texture = LoadTextureFromImage(atlas);
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText() // Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.glyphCount; i++) for (int i = 0; i < font.glyphCount; i++)
@ -577,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 fot 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
@ -674,6 +677,8 @@ 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);
// Load characters images // Load characters images
chars[i].image.width = chw; chars[i].image.width = chw;
chars[i].image.height = chh; chars[i].image.height = chh;
@ -946,7 +951,7 @@ void UnloadFont(Font font)
if (font.texture.id != GetFontDefault().texture.id) if (font.texture.id != GetFontDefault().texture.id)
{ {
UnloadFontData(font.glyphs, font.glyphCount); UnloadFontData(font.glyphs, font.glyphCount);
UnloadTexture(font.texture); if (isGpuReady) UnloadTexture(font.texture);
RL_FREE(font.recs); RL_FREE(font.recs);
TRACELOGD("FONT: Unloaded font data from RAM and VRAM"); TRACELOGD("FONT: Unloaded font data from RAM and VRAM");
@ -1066,7 +1071,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format); byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format);
#endif #endif
byteCount += sprintf(txtData + byteCount, " // Load texture from image\n"); byteCount += sprintf(txtData + byteCount, " // Load texture from image\n");
byteCount += sprintf(txtData + byteCount, " font.texture = LoadTextureFromImage(imFont);\n"); byteCount += sprintf(txtData + byteCount, " if (isGpuReady) font.texture = LoadTextureFromImage(imFont);\n");
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS) #if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n"); byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n");
#endif #endif
@ -1277,7 +1282,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{ {
Vector2 textSize = { 0 }; Vector2 textSize = { 0 };
if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check if ((isGpuReady && (font.texture.id == 0)) || (text == NULL)) return textSize; // Security check
int size = TextLength(text); // Get size in bytes of text int size = TextLength(text); // Get size in bytes of text
int tempByteCounter = 0; // Used to count longer text line num chars int tempByteCounter = 0; // Used to count longer text line num chars
@ -1296,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
@ -1924,6 +1929,7 @@ 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 };
memset(utf8, 0, 6); // Clear static array
int size = 0; // Byte size of codepoint int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f) if (codepoint <= 0x7f)
@ -2257,7 +2263,7 @@ static Font LoadBMFont(const char *fileName)
RL_FREE(imFonts); RL_FREE(imFonts);
font.texture = LoadTextureFromImage(fullFont); if (isGpuReady) font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data // Fill font characters info data
font.baseSize = fontSize; font.baseSize = fontSize;
@ -2299,7 +2305,7 @@ static Font LoadBMFont(const char *fileName)
UnloadImage(fullFont); UnloadImage(fullFont);
UnloadFileText(fileText); UnloadFileText(fileText);
if (font.texture.id == 0) if (isGpuReady && (font.texture.id == 0))
{ {
UnloadFont(font); UnloadFont(font);
font = GetFontDefault(); font = GetFontDefault();

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,13 +600,13 @@ 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)
@ -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;
} }
@ -4566,6 +4458,9 @@ 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.height < 0) dest.height *= -1;
Vector2 topLeft = { 0 }; Vector2 topLeft = { 0 };
Vector2 topRight = { 0 }; Vector2 topRight = { 0 };
Vector2 bottomLeft = { 0 }; Vector2 bottomLeft = { 0 };
@ -5183,6 +5078,22 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
return out; return out;
} }
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
Color ColorLerp(Color color1, Color color2, float factor)
{
Color color = { 0 };
if (factor < 0.0f) factor = 0.0f;
else if (factor > 1.0f) factor = 1.0f;
color.r = (unsigned char)((1.0f - factor)*color1.r + factor*color2.r);
color.g = (unsigned char)((1.0f - factor)*color1.g + factor*color2.g);
color.b = (unsigned char)((1.0f - factor)*color1.b + factor*color2.b);
color.a = (unsigned char)((1.0f - factor)*color1.a + factor*color2.a);
return color;
}
// Get a Color struct from hexadecimal value // Get a Color struct from hexadecimal value
Color GetColor(unsigned int hexValue) Color GetColor(unsigned int hexValue)
{ {

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