Squashed 'libs/raylib/' changes from 3a1d6261e..9b6c09c32
9b6c09c32 Merge pull request #5049 from wwderw/master 0b125a5fd Update Makefile 0b7dda8ab Merge pull request #5050 from katanya04/master 3d93b3026 Update font load message 78a06990c Merge pull request #5041 from PanicTitan/master 82b80a699 Review formatting, avoid variable 71b302846 Review formatting, avoid variable 8823aba9d Update rprand.h 6b9a685ba Merge pull request #5048 from veins1/patch-4 14582a9f0 Merge pull request #5047 from RomainPlmg/#5009-fix-colorreplace-alpha 093e5200d Update Makefile 0405de794 Fix for music stopping too early d03ac97ef GetMusicTimePlayed fix for music shorter than buffer size 34af70866 [rtextures] Fix ImageColorReplace() alpha issue #5009 e00c5eb8b Merge pull request #5043 from vinnyhorgan/master cbea2ff50 Merge pull request #5046 from maiconpintoabreu/updatestream-music 3320a2c83 Fix to prevent UpdateMusicStream to run without music playing e7c043529 Merge pull request #5044 from backspaceoverload/fix-HalfToFloat 44ebf3238 Fix HalfToFloat Mantissa hex value 901afadbf fix warning log macro in rlgl f34e24068 Merge pull request #5042 from Sir-Irk/ImageDrawLineEx_fix fce3102f1 Remove excess comments 9f03d7c42 fixing comments 0c69c43c3 fix ImageDrawLineEx to be able to draw even numbered thicknesses 9e908e4a7 Update core_custom_frame_control.c to work properly on web 20a07a65d Merge pull request #5037 from garrisonhh/fix-gaussian-blur 8dbacafbe fix overflow in cast for ImageBlurGaussian 55a567471 Merge pull request #5036 from sleeptightAnsiC/update_glfw_mappings_h 930890555 [glfw] update mappings.h using GenerateMappings.cmake defbeee1a Merge pull request #5020 from Emil2010/master d972582bc Merge pull request #5025 from zedeckj/master 595756498 Merge pull request #5026 from jonathandw743/sdlfix eaea8e0b0 Merge pull request #5033 from wwderw/master 8ef51850b Update raudio.c a92f67bf3 Merge pull request #5031 from AmityWilder/safety-comments 205b6a092 Merge branch 'raysan5:master' into safety-comments 9f6d37ecb Update raylib_api.* by CI d4f09984a Add safety notes to 'Update_' functions 79c29cbe2 fixed compile error for PLATFORM sdl e91a3697f Fixed typo 910f4083e update dr_libs 7f8dfc6c6 Merge pull request #5018 from maiconpintoabreu/fix-zig-wasm-win-mac f1600a0c7 Fix issue on zig build emscripten run if the user has not installed emsdk 46f01e315 Merge pull request #5013 from maiconpintoabreu/zig-examples 2e74133a6 Merge pull request #5014 from fosskers/colin/cl-binding 7f32b9a96 Merge pull request #5015 from Sir-Irk/gltf_model_fix 8cf932c82 Merge pull request #5016 from Sir-Irk/fix_pbr_example_tangents ed509193d remving w multiply on the tangent itself f86295732 fixing shader tangents to be vec4 bee524e5e fixing offset for processing tangents for gltf loading eef1bac3e fix misspelling 0cae8890b Remove -fno-stack-protector as it is not needed and add requestFullscreen on exported methods 1db006b08 docs: mention another Common Lisp binding 8f50436dc Fix comments 6e9c3acaa Add run examples using zig and emscripten for web bdda18656 Merge pull request #5011 from maiconpintoabreu/update-emsdk-fix-touch d659037fb Update emsdk version for zig build to fix the issue with the EM_BOOL c35e13647 Merge branch 'master' of https://github.com/raysan5/raylib 44f670899 REVIEWED: Avoid `rtext` dependency on `rcore_desktop_sdl` #4959 e09dcf611 Merge pull request #5006 from ElDigoXD/patch-1 6266d0f41 Fix typo on config.h b67737608 Delete shader in case compilation fails 1abac023b Update rcore.c 8b0230f5b Merge pull request #5002 from mlorenc227/master 518ad8b01 Fix ScanDirectoryFilesRecursively 4bc8d3761 Merge pull request #4999 from danilwhale/raylib-cs.bleedingedge 43bad2612 docs: add Raylib-cs.BleedingEdge to the bindings fd4375a74 Merge pull request #4992 from M374LX/rgfw-update 17a618758 Merge pull request #4995 from Not-Nik/zig-raygui-options abf255fbe Merge pull request #4993 from Marcos-cat/master 106bcf460 add uiua bindings to the list 96c898852 Update RGFW 3e336e447 Reviewed warning 59bcf680a Code gardening... 8a3a8ee8e Update shapes_digital_clock.c 533c12c38 Small security tweaks 5f497d068 REVIEWED: `shapes_digital_clock` example cb369f8df Merge pull request #4985 from hmz-rhl/master 3f228f459 [examples] : adding new fancy clock 8d319b100 Merge pull request #4983 from M374LX/miniaudio-update d218db9ee Merge pull request #4982 from LainLayer/rgfw-timeout 59338c2c2 Update raylib_api.* by CI 714de02a8 Merge pull request #4980 from williewillus/pr4980 c81097505 Merge pull request #4981 from garrisonhh/add-build-zig-zon-license 53faf7ae7 Merge pull request #4977 from jestarray/patch-2 bb5b5434a Update miniaudio to v0.11.22 51958d6e2 changed `RGFW_window_eventWait` timeout to -1 b52a9f8a0 Add LICENSE to build.zig.zon 19ae6f2c2 [rshapes] Fix incorrect parameter names in DrawRectangleGradientEx 58a6846c8 Update raylib_api.* by CI 296e3af47 add const qualifier to ImageDrawTriangleFan and ImageDrawTriangleStrip arguments 924c87db3 Merge pull request #4976 from M374LX/rgfw-update-dev 6eeaf1dd5 Update RGFW to 1.7.5-dev c1bb53738 Merge pull request #4974 from M374LX/rgfw-escape-fix 9bf4388a4 Merge pull request #4965 from M374LX/rgfw-update 3414d96ea Update raylib_api.* by CI 20c0c92bd Merge pull request #4963 from meowstr/master bc2b2864e RGFW: fix Escape always closing the window b26f6d34b Allow passing options to raygui in build.zig b9c2ecc44 Merge pull request #4969 from M374LX/update-comments 8f2ecfba4 Update raylib_api.* by CI 341817261 Update comments 015db1641 Merge pull request #4964 from M374LX/axes-comment a9525bfbc Update RGFW to 1.7 16f398b46 Update comment (gamepad axes) 6d5aedbd3 Add DrawEllipseV and DrawEllipseLinesV 913c23648 REVIEWED: `MAX_GAMEPAD_AXES` 341bfb22c REVIEWED: `MAX_GAMEPAD_AXEX` for consistency #4960 2afae1b3e Merge pull request #4962 from M374LX/rgfw-rctrl f9fa63366 Merge pull request #4958 from M374LX/unused-var c0cf57f8f RGFW backend: add missing Right Control key 299f5350a Remove unused variable 2d952d8e9 Update raylib_api.* by CI d7148f5f9 REDESIGNED: Base64 encoding/decoding functions 5ddd13b77 REVIEWED: Hexadecimal formatting to be consistent 8d9c1cecb Update raylib_api.* by CI afb52b19a WARNING: REDESIGNED: `EncodeDataBase64()`, NULL terminated string returned 21f0fe2a7 Removed some spaces e3b9dbe75 Merge pull request #4947 from padmadevd/master b6daa48a9 Update rcore_android.c a1d57e83f Merge pull request #4948 from parzivail/bug/meshnormals 21e711b13 Fix typo in mesh animNormals 5da2d1011 Update rcore_android.c 2be18e2c5 Merge pull request #4944 from Pivok7/master 0ffc8c517 Pbr example fix 8c99a508c REVIEWED: `WindowSizeCallback()`, GLFW a51d33444 Merge branch 'master' of https://github.com/raysan5/raylib 9d4c31533 Update rtext.c 15a0cf89b Merge pull request #4936 from lumenkeyes/master ba3121914 Merge pull request #4937 from Bigfoot71/fix-gen-tangents 5076d5743 Merge pull request #4938 from JeffM2501/const_save_callback 4a1e9931a Update raylib_api.* by CI aa684a33d make save file callback match const correctness of calling function d135eef46 fix and improve `GenMeshTangents` 6f11e27bb fix typo dea6a2477 build.zig fix: link EGL for Android 63b988ade Update raylib_api.* by CI f7d03efb4 REVIEWED: `DecodeDataBase64()`, follow convention: 3083f0cd4 REVIEWED: `SaveFileText()`, const input text 693c9c292 Formatting tweaks 4ac31f7cd Merge pull request #4928 from JeffM2501/unload_default_font ebaa922f6 Properly clean up the default font on unload, it may be reused if the window is created again 7e0727836 Update rprand.h 1402e830b Merge pull request #4926 from karl-zylinski/draw-sphere-normals 6fad12db7 Merge pull request #4927 from lumenkeyes/master 35de7b26a catch error in build.zig eae3fd83d properly detect if abi is android c4b9c0e03 properly generate android triple in build.zig a15548fb5 Add normals to DrawSphereEx 3d6e24af4 Merge pull request #4906 from Bigfoot71/fix-clip 512b1bed4 Merge pull request #4925 from JeffM2501/animated_meshes_GL11 e07e3354a Merge branch 'animated_meshes_GL11' of github.com:JeffM2501/raylib into animated_meshes_GL11 ee2ab11cc Use the animated verts and normals in GL 1.1 if they exist 95c96b345 Use the animated verts and normals in GL 1.1 if they exist 31d63d08e Merge pull request #4922 from Bigfoot71/review-file-dir-2 a7ad2d196 Merge pull request #4918 from JeffM2501/default_font_image_leaks 3d292a6c3 Merge pull request #4923 from JeffM2501/gltf_bone_fix e53a43b7b Assign meshes without bone weights to the bone they are attached to so they animate. 38aec920b makes `path` static in `ScanDirectoryFilesRecursively` 03988d2ce added a NULL check in `UnloadDirectoryFiles` c08714438 Merge branch 'raysan5:master' into fix-clip 82c87d1f6 Merge pull request #4920 from MrScautHD/patch-1 8533d284c Update BINDINGS.md 94c5de33a Make the default font loadable before InitWindow, for use with the image API. Make the default font loader early out if we have already loaded parts of it, so we don't leak memory 461c9c9d9 review tabs a7333a9da review near/far git-subtree-dir: libs/raylib git-subtree-split: 9b6c09c32f7283e849918aef220ec4fa629af8d2
This commit is contained in:
parent
6b853a6601
commit
bf5a3f231b
@ -13,10 +13,12 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
|||||||
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [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 |
|
||||||
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.1-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
|
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
|
||||||
|
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||||
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
|
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
|
||||||
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
||||||
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
|
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
|
||||||
|
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
|
||||||
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
|
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
|
||||||
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
|
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
|
||||||
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
|
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
|
||||||
@ -93,6 +95,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
|||||||
| [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 |
|
||||||
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
|
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
|
||||||
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
|
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
|
||||||
|
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
|
||||||
|
|
||||||
### Utility Wrapers
|
### Utility Wrapers
|
||||||
|
|
||||||
@ -103,6 +106,7 @@ These are utility wrappers for specific languages, they are not required to use
|
|||||||
| [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 |
|
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
||||||
| [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT |
|
| [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT |
|
||||||
|
| [Iris](https://github.com/Marcos-cat/iris) | **5.5** | [Uiua](https://www.uiua.org/) | MIT |
|
||||||
|
|
||||||
### Older or Unmaintained Language Bindings
|
### Older or Unmaintained Language Bindings
|
||||||
|
|
||||||
|
128
build.zig
128
build.zig
@ -4,6 +4,9 @@ const builtin = @import("builtin");
|
|||||||
/// Minimum supported version of Zig
|
/// Minimum supported version of Zig
|
||||||
const min_ver = "0.13.0";
|
const min_ver = "0.13.0";
|
||||||
|
|
||||||
|
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
||||||
|
const emccOutputFile = "index.html";
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
const order = std.SemanticVersion.order;
|
const order = std.SemanticVersion.order;
|
||||||
const parse = std.SemanticVersion.parse;
|
const parse = std.SemanticVersion.parse;
|
||||||
@ -45,6 +48,26 @@ fn emSdkSetupStep(b: *std.Build, emsdk: *std.Build.Dependency) !?*std.Build.Step
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from Not-Nik/raylib-zig
|
||||||
|
fn emscriptenRunStep(b: *std.Build, emsdk: *std.Build.Dependency, examplePath: []const u8) !*std.Build.Step.Run {
|
||||||
|
const dot_emsc_path = emsdk.path("upstream/emscripten/cache/sysroot/include").getPath(b);
|
||||||
|
// If compiling on windows , use emrun.bat.
|
||||||
|
const emrunExe = switch (builtin.os.tag) {
|
||||||
|
.windows => "emrun.bat",
|
||||||
|
else => "emrun",
|
||||||
|
};
|
||||||
|
var emrun_run_arg = try b.allocator.alloc(u8, dot_emsc_path.len + emrunExe.len + 1);
|
||||||
|
defer b.allocator.free(emrun_run_arg);
|
||||||
|
|
||||||
|
if (b.sysroot == null) {
|
||||||
|
emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ emsdk.path("upstream/emscripten").getPath(b), emrunExe });
|
||||||
|
} else {
|
||||||
|
emrun_run_arg = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ dot_emsc_path, emrunExe });
|
||||||
|
}
|
||||||
|
const run_cmd = b.addSystemCommand(&.{ emrun_run_arg, examplePath });
|
||||||
|
return run_cmd;
|
||||||
|
}
|
||||||
|
|
||||||
/// A list of all flags from `src/config.h` that one may override
|
/// A list of all flags from `src/config.h` that one may override
|
||||||
const config_h_flags = outer: {
|
const config_h_flags = outer: {
|
||||||
// Set this value higher if compile errors happen as `src/config.h` gets larger
|
// Set this value higher if compile errors happen as `src/config.h` gets larger
|
||||||
@ -205,7 +228,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
raylib.root_module.addCMacro("PLATFORM_DRM", "");
|
raylib.root_module.addCMacro("PLATFORM_DRM", "");
|
||||||
raylib.root_module.addCMacro("EGL_NO_X11", "");
|
raylib.root_module.addCMacro("EGL_NO_X11", "");
|
||||||
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
|
raylib.root_module.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
|
||||||
} else if (target.result.abi == .android) {
|
} else if (target.result.abi.isAndroid()) {
|
||||||
|
|
||||||
//these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems
|
//these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems
|
||||||
const hostTuple = switch (builtin.target.os.tag) {
|
const hostTuple = switch (builtin.target.os.tag) {
|
||||||
@ -215,7 +238,14 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
else => @panic("unsupported host OS"),
|
else => @panic("unsupported host OS"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const androidTriple = try target.result.linuxTriple(b.allocator);
|
const androidTriple = switch (target.result.cpu.arch) {
|
||||||
|
.x86 => "i686-linux-android",
|
||||||
|
.x86_64 => "x86_64-linux-android",
|
||||||
|
.arm => "arm-linux-androideabi",
|
||||||
|
.aarch64 => "aarch64-linux-android",
|
||||||
|
.riscv64 => "riscv64-linux-android",
|
||||||
|
else => error.InvalidAndroidTarget,
|
||||||
|
} catch @panic("invalid android target!");
|
||||||
const androidNdkPathString: []const u8 = options.android_ndk;
|
const androidNdkPathString: []const u8 = options.android_ndk;
|
||||||
if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set");
|
if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set");
|
||||||
const androidApiLevel: []const u8 = options.android_api_version;
|
const androidApiLevel: []const u8 = options.android_api_version;
|
||||||
@ -249,6 +279,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
raylib.root_module.linkSystemLibrary("GLESv2", .{});
|
raylib.root_module.linkSystemLibrary("GLESv2", .{});
|
||||||
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
|
||||||
}
|
}
|
||||||
|
raylib.root_module.linkSystemLibrary("EGL", .{});
|
||||||
|
|
||||||
setDesktopPlatform(raylib, .android);
|
setDesktopPlatform(raylib, .android);
|
||||||
} else {
|
} else {
|
||||||
@ -331,7 +362,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
setDesktopPlatform(raylib, options.platform);
|
setDesktopPlatform(raylib, options.platform);
|
||||||
},
|
},
|
||||||
.emscripten => {
|
.emscripten => {
|
||||||
// Include emscripten for cross compilation
|
|
||||||
if (b.lazyDependency("emsdk", .{})) |dep| {
|
if (b.lazyDependency("emsdk", .{})) |dep| {
|
||||||
if (try emSdkSetupStep(b, dep)) |emSdkStep| {
|
if (try emSdkSetupStep(b, dep)) |emSdkStep| {
|
||||||
raylib.step.dependOn(&emSdkStep.step);
|
raylib.step.dependOn(&emSdkStep.step);
|
||||||
@ -358,8 +388,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||||||
return raylib;
|
return raylib;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency) void {
|
pub fn addRaygui(b: *std.Build, raylib: *std.Build.Step.Compile, raygui_dep: *std.Build.Dependency, options: Options) void {
|
||||||
const raylib_dep = b.dependencyFromBuildZig(@This(), .{});
|
const raylib_dep = b.dependencyFromBuildZig(@This(), options);
|
||||||
var gen_step = b.addWriteFiles();
|
var gen_step = b.addWriteFiles();
|
||||||
raylib.step.dependOn(&gen_step.step);
|
raylib.step.dependOn(&gen_step.step);
|
||||||
|
|
||||||
@ -503,12 +533,9 @@ fn addExamples(
|
|||||||
optimize: std.builtin.OptimizeMode,
|
optimize: std.builtin.OptimizeMode,
|
||||||
raylib: *std.Build.Step.Compile,
|
raylib: *std.Build.Step.Compile,
|
||||||
) !*std.Build.Step {
|
) !*std.Build.Step {
|
||||||
if (target.result.os.tag == .emscripten) {
|
|
||||||
return &b.addFail("Emscripten building via Zig unsupported").step;
|
|
||||||
}
|
|
||||||
|
|
||||||
const all = b.step(module, "All " ++ module ++ " examples");
|
const all = b.step(module, "All " ++ module ++ " examples");
|
||||||
const module_subpath = b.pathJoin(&.{ "examples", module });
|
const module_subpath = b.pathJoin(&.{ "examples", module });
|
||||||
|
const module_resources = b.pathJoin(&.{ module_subpath, "resources@resources" });
|
||||||
var dir = try std.fs.cwd().openDir(b.pathFromRoot(module_subpath), .{ .iterate = true });
|
var dir = try std.fs.cwd().openDir(b.pathFromRoot(module_subpath), .{ .iterate = true });
|
||||||
defer if (comptime builtin.zig_version.minor >= 12) dir.close();
|
defer if (comptime builtin.zig_version.minor >= 12) dir.close();
|
||||||
|
|
||||||
@ -522,6 +549,88 @@ fn addExamples(
|
|||||||
// zig's mingw headers do not include pthread.h
|
// zig's mingw headers do not include pthread.h
|
||||||
if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue;
|
if (std.mem.eql(u8, "core_loading_thread", name) and target.result.os.tag == .windows) continue;
|
||||||
|
|
||||||
|
if (target.result.os.tag == .emscripten) {
|
||||||
|
const exe_lib = b.addStaticLibrary(.{
|
||||||
|
.name = name,
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
exe_lib.addCSourceFile(.{
|
||||||
|
.file = b.path(path),
|
||||||
|
.flags = &.{},
|
||||||
|
});
|
||||||
|
exe_lib.linkLibC();
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, name, "rlgl_standalone")) {
|
||||||
|
//TODO: Make rlgl_standalone example work
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (std.mem.eql(u8, name, "raylib_opengl_interop")) {
|
||||||
|
//TODO: Make raylib_opengl_interop example work
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
exe_lib.linkLibrary(raylib);
|
||||||
|
|
||||||
|
// Include emscripten for cross compilation
|
||||||
|
if (b.lazyDependency("emsdk", .{})) |emsdk_dep| {
|
||||||
|
if (try emSdkSetupStep(b, emsdk_dep)) |emSdkStep| {
|
||||||
|
exe_lib.step.dependOn(&emSdkStep.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
exe_lib.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||||
|
|
||||||
|
// Create the output directory because emcc can't do it.
|
||||||
|
const emccOutputDirExample = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str });
|
||||||
|
const mkdir_command = switch (builtin.os.tag) {
|
||||||
|
.windows => b.addSystemCommand(&.{ "cmd.exe", "/c", "if", "not", "exist", emccOutputDirExample, "mkdir", emccOutputDirExample }),
|
||||||
|
else => b.addSystemCommand(&.{ "mkdir", "-p", emccOutputDirExample }),
|
||||||
|
};
|
||||||
|
|
||||||
|
const emcc_exe = switch (builtin.os.tag) {
|
||||||
|
.windows => "emcc.bat",
|
||||||
|
else => "emcc",
|
||||||
|
};
|
||||||
|
|
||||||
|
const emcc_exe_path = b.pathJoin(&.{ emsdk_dep.path("upstream/emscripten").getPath(b), emcc_exe });
|
||||||
|
const emcc_command = b.addSystemCommand(&[_][]const u8{emcc_exe_path});
|
||||||
|
emcc_command.step.dependOn(&mkdir_command.step);
|
||||||
|
const emccOutputDirExampleWithFile = b.pathJoin(&.{ emccOutputDir, name, std.fs.path.sep_str, emccOutputFile });
|
||||||
|
emcc_command.addArgs(&[_][]const u8{
|
||||||
|
"-o",
|
||||||
|
emccOutputDirExampleWithFile,
|
||||||
|
"-sFULL-ES3=1",
|
||||||
|
"-sUSE_GLFW=3",
|
||||||
|
"-sSTACK_OVERFLOW_CHECK=1",
|
||||||
|
"-sEXPORTED_RUNTIME_METHODS=['requestFullscreen']",
|
||||||
|
"-sASYNCIFY",
|
||||||
|
"-O0",
|
||||||
|
"--emrun",
|
||||||
|
"--preload-file",
|
||||||
|
module_resources,
|
||||||
|
"--shell-file",
|
||||||
|
b.path("src/shell.html").getPath(b),
|
||||||
|
});
|
||||||
|
|
||||||
|
const link_items: []const *std.Build.Step.Compile = &.{
|
||||||
|
raylib,
|
||||||
|
exe_lib,
|
||||||
|
};
|
||||||
|
for (link_items) |item| {
|
||||||
|
emcc_command.addFileArg(item.getEmittedBin());
|
||||||
|
emcc_command.step.dependOn(&item.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_step = try emscriptenRunStep(b, emsdk_dep, emccOutputDirExampleWithFile);
|
||||||
|
run_step.step.dependOn(&emcc_command.step);
|
||||||
|
run_step.addArg("--no_browser");
|
||||||
|
const run_option = b.step(name, name);
|
||||||
|
|
||||||
|
run_option.dependOn(&run_step.step);
|
||||||
|
|
||||||
|
all.dependOn(&emcc_command.step);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
.target = target,
|
.target = target,
|
||||||
@ -588,6 +697,7 @@ fn addExamples(
|
|||||||
|
|
||||||
all.dependOn(&install_cmd.step);
|
all.dependOn(&install_cmd.step);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
.emsdk = .{
|
.emsdk = .{
|
||||||
.url = "git+https://github.com/emscripten-core/emsdk#3.1.50",
|
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
|
||||||
.hash = "N-V-__8AALRTBQDo_pUJ8IQ-XiIyYwDKQVwnr7-7o5kvPDGE",
|
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -23,5 +23,6 @@
|
|||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
"examples",
|
"examples",
|
||||||
|
"LICENSE",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -547,7 +547,8 @@ SHAPES = \
|
|||||||
shapes/shapes_rectangle_advanced \
|
shapes/shapes_rectangle_advanced \
|
||||||
shapes/shapes_rectangle_scaling \
|
shapes/shapes_rectangle_scaling \
|
||||||
shapes/shapes_splines_drawing \
|
shapes/shapes_splines_drawing \
|
||||||
shapes/shapes_top_down_lights
|
shapes/shapes_top_down_lights \
|
||||||
|
shapes/shapes_digital_clock
|
||||||
|
|
||||||
TEXTURES = \
|
TEXTURES = \
|
||||||
textures/textures_background_scrolling \
|
textures/textures_background_scrolling \
|
||||||
|
@ -429,7 +429,8 @@ SHAPES = \
|
|||||||
shapes/shapes_rectangle_advanced \
|
shapes/shapes_rectangle_advanced \
|
||||||
shapes/shapes_rectangle_scaling \
|
shapes/shapes_rectangle_scaling \
|
||||||
shapes/shapes_splines_drawing \
|
shapes/shapes_splines_drawing \
|
||||||
shapes/shapes_top_down_lights
|
shapes/shapes_top_down_lights \
|
||||||
|
shapes/shapes_digital_clock
|
||||||
|
|
||||||
TEXTURES = \
|
TEXTURES = \
|
||||||
textures/textures_background_scrolling \
|
textures/textures_background_scrolling \
|
||||||
|
@ -85,39 +85,39 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
|
|||||||
| 51 | [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) |
|
| 51 | [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) |
|
||||||
| 52 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | <img src="shapes/shapes_rectangle_advanced.png" alt="shapes_rectangle_advanced" width="80"> | ⭐️⭐️⭐️⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) |
|
| 52 | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | <img src="shapes/shapes_rectangle_advanced.png" alt="shapes_rectangle_advanced" width="80"> | ⭐️⭐️⭐️⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) |
|
||||||
| 53 | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | <img src="shapes/shapes_splines_drawing.png" alt="shapes_splines_drawing" width="80"> | ⭐️⭐️⭐️☆ | 5.0 | 5.0 | [Ray](https://github.com/raysan5) |
|
| 53 | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | <img src="shapes/shapes_splines_drawing.png" alt="shapes_splines_drawing" width="80"> | ⭐️⭐️⭐️☆ | 5.0 | 5.0 | [Ray](https://github.com/raysan5) |
|
||||||
|
| 54 | [shapes_digital_clock](shapes/shapes_digital_clock.c) | <img src="shapes/shapes_digital_clock.png" alt="shapes_digital_clock" width="80"> | ⭐️⭐️☆☆ | 5.5 | 5.5 | [Hamza RAHAL](https://github.com/rhmz-rhl) |
|
||||||
### category: textures
|
### category: textures
|
||||||
|
|
||||||
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/textures.c) modul
|
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/textures.c) modul
|
||||||
|
|
||||||
| ## | 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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 54 | [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) |
|
| 55 | [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) |
|
||||||
| 55 | [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) |
|
| 56 | [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) |
|
||||||
| 56 | [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) |
|
| 57 | [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) |
|
||||||
| 57 | [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 | [Wilhem Barbier](https://github.com/nounoursheureux) |
|
| 58 | [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 | [Wilhem Barbier](https://github.com/nounoursheureux) |
|
||||||
| 58 | [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) |
|
| 59 | [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) |
|
||||||
| 59 | [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) |
|
| 60 | [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) |
|
||||||
| 60 | [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) |
|
| 61 | [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) |
|
||||||
| 61 | [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) |
|
| 62 | [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) |
|
||||||
| 62 | [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) |
|
| 63 | [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) |
|
||||||
| 63 | [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) |
|
| 64 | [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) |
|
||||||
| 64 | [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) |
|
| 65 | [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) |
|
||||||
| 65 | [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) |
|
| 66 | [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) |
|
||||||
| 66 | [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) |
|
| 67 | [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) |
|
||||||
| 67 | [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) |
|
| 68 | [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) |
|
||||||
| 68 | [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) |
|
| 69 | [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) |
|
||||||
| 69 | [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) |
|
| 70 | [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) |
|
||||||
| 70 | [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) |
|
| 71 | [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) |
|
||||||
| 71 | [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) |
|
| 72 | [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) |
|
||||||
| 72 | [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) |
|
| 73 | [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) |
|
||||||
| 73 | [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/chriscamacho) |
|
| 74 | [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/chriscamacho) |
|
||||||
| 74 | [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) |
|
| 75 | [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) |
|
||||||
| 75 | [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) |
|
| 76 | [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) |
|
||||||
| 76 | [textures_image_kernel](textures/textures_image_kernel.c) | <img src="textures/textures_image_kernel.png" alt="textures_image_kernel" width="80"> | ⭐️⭐️⭐️⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) |
|
| 77 | [textures_image_kernel](textures/textures_image_kernel.c) | <img src="textures/textures_image_kernel.png" alt="textures_image_kernel" width="80"> | ⭐️⭐️⭐️⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) |
|
||||||
| 77 | [textures_image_channel](textures/textures_image_channel.c) | <img src="textures/textures_image_channel.png" alt="textures_image_channel" width="80"> | ⭐️⭐️☆☆ | 5.1-dev | 5.1-dev | [Bruno Cabral](https://github.com/brccabral) |
|
| 78 | [textures_image_channel](textures/textures_image_channel.c) | <img src="textures/textures_image_channel.png" alt="textures_image_channel" width="80"> | ⭐️⭐️☆☆ | 5.1-dev | 5.1-dev | [Bruno Cabral](https://github.com/brccabral) |
|
||||||
| 78 | [textures_image_rotate](textures/textures_image_rotate.c) | <img src="textures/textures_image_rotate.png" alt="textures_image_rotate" width="80"> | ⭐️⭐️☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
|
| 79 | [textures_image_rotate](textures/textures_image_rotate.c) | <img src="textures/textures_image_rotate.png" alt="textures_image_rotate" width="80"> | ⭐️⭐️☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) |
|
||||||
| 79 | [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
|
| 80 | [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||||
|
|
||||||
### category: text
|
### category: text
|
||||||
|
|
||||||
@ -125,18 +125,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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 80 | [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) |
|
| 81 | [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) |
|
||||||
| 81 | [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) |
|
| 82 | [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) |
|
||||||
| 82 | [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) |
|
| 83 | [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) |
|
||||||
| 83 | [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) |
|
| 84 | [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) |
|
||||||
| 84 | [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) |
|
| 85 | [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) |
|
||||||
| 85 | [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) |
|
| 86 | [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) |
|
||||||
| 86 | [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) |
|
| 87 | [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) |
|
||||||
| 87 | [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) |
|
| 88 | [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) |
|
||||||
| 88 | [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) |
|
| 89 | [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) |
|
||||||
| 89 | [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) |
|
| 90 | [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) |
|
||||||
| 90 | [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) |
|
| 91 | [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) |
|
||||||
| 91 | [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) |
|
| 92 | [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
|
||||||
|
|
||||||
@ -144,29 +144,29 @@ 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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 92 | [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) |
|
| 93 | [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) |
|
||||||
| 93 | [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) |
|
| 94 | [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) |
|
||||||
| 94 | [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) |
|
| 95 | [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) |
|
||||||
| 95 | [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) |
|
| 96 | [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) |
|
||||||
| 96 | [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) |
|
| 97 | [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) |
|
||||||
| 97 | [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) |
|
| 98 | [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) |
|
||||||
| 98 | [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) |
|
| 99 | [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) |
|
||||||
| 99 | [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) |
|
| 100 | [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) |
|
||||||
| 100 | [models_loading](models/models_loading.c) | <img src="models/models_loading.png" alt="models_loading" width="80"> | ⭐️☆☆☆ | 2.0 | 4.2 | [Ray](https://github.com/raysan5) |
|
| 101 | [models_loading](models/models_loading.c) | <img src="models/models_loading.png" alt="models_loading" width="80"> | ⭐️☆☆☆ | 2.0 | 4.2 | [Ray](https://github.com/raysan5) |
|
||||||
| 101 | [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) |
|
| 102 | [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) |
|
||||||
| 102 | [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) |
|
| 103 | [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) |
|
||||||
| 103 | [models_loading_m3d](models/models_loading_m3d.c) | <img src="models/models_loading_m3d.png" alt="models_loading_m3d" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [bzt](https://bztsrc.gitlab.io/model3d) |
|
| 104 | [models_loading_m3d](models/models_loading_m3d.c) | <img src="models/models_loading_m3d.png" alt="models_loading_m3d" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [bzt](https://bztsrc.gitlab.io/model3d) |
|
||||||
| 104 | [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) |
|
| 105 | [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) |
|
||||||
| 105 | [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) |
|
| 106 | [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) |
|
||||||
| 106 | [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) |
|
| 107 | [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) |
|
||||||
| 107 | [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) |
|
| 108 | [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) |
|
||||||
| 108 | [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) |
|
| 109 | [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) |
|
||||||
| 109 | [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) |
|
| 110 | [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) |
|
||||||
| 110 | [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) |
|
| 111 | [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) |
|
||||||
| 111 | [models_draw_cube_texture](models/models_draw_cube_texture.c) | <img src="models/models_draw_cube_texture.png" alt="models_draw_cube_texture" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Ray](https://github.com/raysan5) |
|
| 112 | [models_draw_cube_texture](models/models_draw_cube_texture.c) | <img src="models/models_draw_cube_texture.png" alt="models_draw_cube_texture" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Ray](https://github.com/raysan5) |
|
||||||
| 112 | [models_gpu_skinning](models/models_gpu_skinning.c) | <img src="models/models_gpu_skinning.png" alt="models_gpu_skinning" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) |
|
| 113 | [models_gpu_skinning](models/models_gpu_skinning.c) | <img src="models/models_gpu_skinning.png" alt="models_gpu_skinning" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) |
|
||||||
| 113 | [models_bone_socket](models/models_bone_socket.c) | <img src="models/models_bone_socket.png" alt="models_bone_socket" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) |
|
| 114 | [models_bone_socket](models/models_bone_socket.c) | <img src="models/models_bone_socket.png" alt="models_bone_socket" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) |
|
||||||
| 114 | [models_tesseract_view](models/models_tesseract_view.c) | <img src="models/models_tesseract_view.png" alt="models_tesseract_view" width="80"> | ⭐️⭐️☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) |
|
| 115 | [models_tesseract_view](models/models_tesseract_view.c) | <img src="models/models_tesseract_view.png" alt="models_tesseract_view" width="80"> | ⭐️⭐️☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) |
|
||||||
|
|
||||||
### category: shaders
|
### category: shaders
|
||||||
|
|
||||||
@ -174,34 +174,34 @@ 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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 115 | [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/chriscamacho) |
|
| 116 | [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/chriscamacho) |
|
||||||
| 116 | [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) |
|
| 117 | [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) |
|
||||||
| 117 | [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) |
|
| 118 | [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) |
|
||||||
| 118 | [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) |
|
| 119 | [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) |
|
||||||
| 119 | [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) |
|
| 120 | [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) |
|
||||||
| 120 | [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) |
|
| 121 | [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) |
|
||||||
| 121 | [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) |
|
| 122 | [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) |
|
||||||
| 122 | [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/ciessielski) |
|
| 123 | [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/ciessielski) |
|
||||||
| 123 | [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) |
|
| 124 | [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) |
|
||||||
| 124 | [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) |
|
| 125 | [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) |
|
||||||
| 125 | [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 | [Josh Colclough](https://github.com/joshcol9232) |
|
| 126 | [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 | [Josh Colclough](https://github.com/joshcol9232) |
|
||||||
| 126 | [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) |
|
| 127 | [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) |
|
||||||
| 127 | [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/chriscamacho) |
|
| 128 | [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/chriscamacho) |
|
||||||
| 128 | [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/chriscamacho) |
|
| 129 | [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/chriscamacho) |
|
||||||
| 129 | [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) |
|
| 130 | [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) |
|
||||||
| 130 | [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) |
|
| 131 | [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) |
|
||||||
| 131 | [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) |
|
| 132 | [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) |
|
||||||
| 132 | [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/chriscamacho) |
|
| 133 | [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/chriscamacho) |
|
||||||
| 133 | [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) |
|
| 134 | [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) |
|
||||||
| 134 | [shaders_hybrid_render](shaders/shaders_hybrid_render.c) | <img src="shaders/shaders_hybrid_render.png" alt="shaders_hybrid_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
| 135 | [shaders_hybrid_render](shaders/shaders_hybrid_render.c) | <img src="shaders/shaders_hybrid_render.png" alt="shaders_hybrid_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
||||||
| 135 | [shaders_texture_tiling](shaders/shaders_texture_tiling.c) | <img src="shaders/shaders_texture_tiling.png" alt="shaders_texture_tiling" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Luis Almeida](https://github.com/luis605) |
|
| 136 | [shaders_texture_tiling](shaders/shaders_texture_tiling.c) | <img src="shaders/shaders_texture_tiling.png" alt="shaders_texture_tiling" width="80"> | ⭐️⭐️☆☆ | 4.5 | 4.5 | [Luis Almeida](https://github.com/luis605) |
|
||||||
| 136 | [shaders_shadowmap](shaders/shaders_shadowmap.c) | <img src="shaders/shaders_shadowmap.png" alt="shaders_shadowmap" width="80"> | ⭐️⭐️⭐️⭐️ | 5.0 | 5.0 | [TheManTheMythTheGameDev](https://github.com/TheManTheMythTheGameDev) |
|
| 137 | [shaders_shadowmap](shaders/shaders_shadowmap.c) | <img src="shaders/shaders_shadowmap.png" alt="shaders_shadowmap" width="80"> | ⭐️⭐️⭐️⭐️ | 5.0 | 5.0 | [TheManTheMythTheGameDev](https://github.com/TheManTheMythTheGameDev) |
|
||||||
| 137 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | <img src="shaders/shaders_vertex_displacement.png" alt="shaders_vertex_displacement" width="80"> | ⭐️⭐️⭐️☆ | 5.0 | 4.5 | [Alex ZH](https://github.com/ZzzhHe) |
|
| 138 | [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | <img src="shaders/shaders_vertex_displacement.png" alt="shaders_vertex_displacement" width="80"> | ⭐️⭐️⭐️☆ | 5.0 | 4.5 | [Alex ZH](https://github.com/ZzzhHe) |
|
||||||
| 138 | [shaders_write_depth](shaders/shaders_write_depth.c) | <img src="shaders/shaders_write_depth.png" alt="shaders_write_depth" width="80"> | ⭐️⭐️☆☆ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
| 139 | [shaders_write_depth](shaders/shaders_write_depth.c) | <img src="shaders/shaders_write_depth.png" alt="shaders_write_depth" width="80"> | ⭐️⭐️☆☆ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
||||||
| 139 | [shaders_basic_pbr](shaders/shaders_basic_pbr.c) | <img src="shaders/shaders_basic_pbr.png" alt="shaders_basic_pbr" width="80"> | ⭐️⭐️⭐️⭐️ | 5.0 | 5.1-dev | [Afan OLOVCIC](https://github.com/_DevDad) |
|
| 140 | [shaders_basic_pbr](shaders/shaders_basic_pbr.c) | <img src="shaders/shaders_basic_pbr.png" alt="shaders_basic_pbr" width="80"> | ⭐️⭐️⭐️⭐️ | 5.0 | 5.1-dev | [Afan OLOVCIC](https://github.com/_DevDad) |
|
||||||
| 140 | [shaders_lightmap](shaders/shaders_lightmap.c) | <img src="shaders/shaders_lightmap.png" alt="shaders_lightmap" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
|
| 141 | [shaders_lightmap](shaders/shaders_lightmap.c) | <img src="shaders/shaders_lightmap.png" alt="shaders_lightmap" width="80"> | ⭐️⭐️⭐️☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
|
||||||
| 141 | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width=80> | ⭐️⭐️⭐️☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
|
| 142 | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width=80> | ⭐️⭐️⭐️☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
|
||||||
| 142 | [shaders_view_depth](shaders/shaders_view_depth.c) | <img src="shaders/shaders_view_depth.png" alt="shaders_view_depth" width="80"> | ⭐️⭐️⭐️☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
|
| 143 | [shaders_view_depth](shaders/shaders_view_depth.c) | <img src="shaders/shaders_view_depth.png" alt="shaders_view_depth" width="80"> | ⭐️⭐️⭐️☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
|
||||||
|
|
||||||
### category: audio
|
### category: audio
|
||||||
|
|
||||||
@ -209,26 +209,26 @@ 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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 142 | [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) |
|
| 144 | [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) |
|
||||||
| 143 | [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) |
|
| 145 | [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) |
|
||||||
| 144 | [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) |
|
| 146 | [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) |
|
||||||
| 145 | [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) |
|
| 147 | [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) |
|
||||||
| 146 | [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
|
| 148 | [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
|
||||||
| 147 | [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) |
|
| 149 | [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) |
|
||||||
| 148 | [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) |
|
| 150 [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||||
| 149 | [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐️⭐️☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
|
| 151 | [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐️⭐️☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
|
||||||
|
|
||||||
### category: others
|
### category: others
|
||||||
|
|
||||||
Examples showing raylib misc functionality that does not fit in other categories, like standalone modules usage or examples integrating external libraries.
|
Ex150amples showing raylib misc functionality that does not fit in other categories, like standalone modules usage or examples integrating external libraries.
|
||||||
|
|
||||||
| ## | 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 |
|
||||||
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
|----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||||
| 150 | [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) |
|
| 152 | [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) |
|
||||||
| 151 | [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) |
|
| 153 | [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) |
|
||||||
| 152 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
|
| 154 | [easings_testbed](others/easings_testbed.c) | <img src="others/easings_testbed.png" alt="easings_testbed" width="80"> | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
|
||||||
| 153 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) |
|
| 155 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | <img src="others/raylib_opengl_interop.png" alt="raylib_opengl_interop" width="80"> | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) |
|
||||||
| 154 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
|
| 156 | [embedded_files_loading](others/embedded_files_loading.c) | <img src="others/embedded_files_loading.png" alt="embedded_files_loading" width="80"> | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
|
||||||
| 155 | [raymath_vector_angle](others/raymath_vector_angle.c) | <img src="others/raymath_vector_angle.png" alt="raymath_vector_angle" width="80"> | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) |
|
| 157 | [raymath_vector_angle](others/raymath_vector_angle.c) | <img src="others/raymath_vector_angle.png" alt="raymath_vector_angle" width="80"> | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) |
|
||||||
|
|
||||||
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!
|
||||||
|
@ -61,7 +61,9 @@ int main(void)
|
|||||||
{
|
{
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifndef PLATFORM_WEB // NOTE: On non web platforms the PollInputEvents just works before the inputs checks
|
||||||
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||||
|
#endif
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
|
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
|
||||||
|
|
||||||
@ -76,6 +78,10 @@ int main(void)
|
|||||||
if (position >= GetScreenWidth()) position = 0;
|
if (position >= GetScreenWidth()) position = 0;
|
||||||
timeCounter += deltaTime; // We count time (seconds)
|
timeCounter += deltaTime; // We count time (seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLATFORM_WEB // NOTE: On web platform for some reason the PollInputEvents only works after the inputs check, so just call it after check all your inputs (on web)
|
||||||
|
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||||
|
#endif
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
attribute vec3 vertexPosition;
|
attribute vec3 vertexPosition;
|
||||||
attribute vec2 vertexTexCoord;
|
attribute vec2 vertexTexCoord;
|
||||||
attribute vec3 vertexNormal;
|
attribute vec3 vertexNormal;
|
||||||
attribute vec3 vertexTangent;
|
attribute vec4 vertexTangent;
|
||||||
attribute vec4 vertexColor;
|
attribute vec4 vertexColor;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
@ -52,7 +52,7 @@ mat3 transpose(mat3 m)
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Compute binormal from vertex normal and tangent
|
// Compute binormal from vertex normal and tangent
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w;
|
||||||
|
|
||||||
// Compute fragment normal based on normal transformations
|
// Compute fragment normal based on normal transformations
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
@ -62,7 +62,7 @@ void main()
|
|||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz);
|
||||||
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
||||||
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
||||||
fragBinormal = cross(fragNormal, fragTangent);
|
fragBinormal = cross(fragNormal, fragTangent);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
attribute vec3 vertexPosition;
|
attribute vec3 vertexPosition;
|
||||||
attribute vec2 vertexTexCoord;
|
attribute vec2 vertexTexCoord;
|
||||||
attribute vec3 vertexNormal;
|
attribute vec3 vertexNormal;
|
||||||
attribute vec3 vertexTangent;
|
attribute vec4 vertexTangent;
|
||||||
attribute vec4 vertexColor;
|
attribute vec4 vertexColor;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
@ -52,7 +52,7 @@ mat3 transpose(mat3 m)
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Compute binormal from vertex normal and tangent
|
// Compute binormal from vertex normal and tangent
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w;
|
||||||
|
|
||||||
// Compute fragment normal based on normal transformations
|
// Compute fragment normal based on normal transformations
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
@ -62,7 +62,7 @@ void main()
|
|||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz);
|
||||||
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
||||||
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
||||||
fragBinormal = cross(fragNormal, fragTangent);
|
fragBinormal = cross(fragNormal, fragTangent);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
in vec3 vertexPosition;
|
in vec3 vertexPosition;
|
||||||
in vec2 vertexTexCoord;
|
in vec2 vertexTexCoord;
|
||||||
in vec3 vertexNormal;
|
in vec3 vertexNormal;
|
||||||
in vec3 vertexTangent;
|
in vec4 vertexTangent;
|
||||||
in vec4 vertexColor;
|
in vec4 vertexColor;
|
||||||
|
|
||||||
// Input uniform values
|
// Input uniform values
|
||||||
@ -26,7 +26,7 @@ const float normalOffset = 0.1;
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Compute binormal from vertex normal and tangent
|
// Compute binormal from vertex normal and tangent
|
||||||
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
|
vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w;
|
||||||
|
|
||||||
// Compute fragment normal based on normal transformations
|
// Compute fragment normal based on normal transformations
|
||||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||||
@ -36,7 +36,7 @@ void main()
|
|||||||
|
|
||||||
fragTexCoord = vertexTexCoord*2.0;
|
fragTexCoord = vertexTexCoord*2.0;
|
||||||
fragNormal = normalize(normalMatrix*vertexNormal);
|
fragNormal = normalize(normalMatrix*vertexNormal);
|
||||||
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
|
vec3 fragTangent = normalize(normalMatrix*vertexTangent.xyz);
|
||||||
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
|
||||||
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
|
||||||
fragBinormal = cross(fragNormal, fragTangent);
|
fragBinormal = cross(fragNormal, fragTangent);
|
||||||
|
@ -125,6 +125,8 @@ int main()
|
|||||||
SetShaderValue(shader, GetShaderLocation(shader, "ambient"), &ambientIntensity, SHADER_UNIFORM_FLOAT);
|
SetShaderValue(shader, GetShaderLocation(shader, "ambient"), &ambientIntensity, SHADER_UNIFORM_FLOAT);
|
||||||
|
|
||||||
// Get location for shader parameters that can be modified in real time
|
// Get location for shader parameters that can be modified in real time
|
||||||
|
int metallicValueLoc = GetShaderLocation(shader, "metallicValue");
|
||||||
|
int roughnessValueLoc = GetShaderLocation(shader, "roughnessValue");
|
||||||
int emissiveIntensityLoc = GetShaderLocation(shader, "emissivePower");
|
int emissiveIntensityLoc = GetShaderLocation(shader, "emissivePower");
|
||||||
int emissiveColorLoc = GetShaderLocation(shader, "emissiveColor");
|
int emissiveColorLoc = GetShaderLocation(shader, "emissiveColor");
|
||||||
int textureTilingLoc = GetShaderLocation(shader, "tiling");
|
int textureTilingLoc = GetShaderLocation(shader, "tiling");
|
||||||
@ -141,7 +143,7 @@ int main()
|
|||||||
|
|
||||||
// Setup materials[0].maps default parameters
|
// Setup materials[0].maps default parameters
|
||||||
car.materials[0].maps[MATERIAL_MAP_ALBEDO].color = WHITE;
|
car.materials[0].maps[MATERIAL_MAP_ALBEDO].color = WHITE;
|
||||||
car.materials[0].maps[MATERIAL_MAP_METALNESS].value = 0.0f;
|
car.materials[0].maps[MATERIAL_MAP_METALNESS].value = 1.0f;
|
||||||
car.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value = 0.0f;
|
car.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value = 0.0f;
|
||||||
car.materials[0].maps[MATERIAL_MAP_OCCLUSION].value = 1.0f;
|
car.materials[0].maps[MATERIAL_MAP_OCCLUSION].value = 1.0f;
|
||||||
car.materials[0].maps[MATERIAL_MAP_EMISSION].color = (Color){ 255, 162, 0, 255 };
|
car.materials[0].maps[MATERIAL_MAP_EMISSION].color = (Color){ 255, 162, 0, 255 };
|
||||||
@ -163,8 +165,8 @@ int main()
|
|||||||
floor.materials[0].shader = shader;
|
floor.materials[0].shader = shader;
|
||||||
|
|
||||||
floor.materials[0].maps[MATERIAL_MAP_ALBEDO].color = WHITE;
|
floor.materials[0].maps[MATERIAL_MAP_ALBEDO].color = WHITE;
|
||||||
floor.materials[0].maps[MATERIAL_MAP_METALNESS].value = 0.0f;
|
floor.materials[0].maps[MATERIAL_MAP_METALNESS].value = 0.8f;
|
||||||
floor.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value = 0.0f;
|
floor.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value = 0.1f;
|
||||||
floor.materials[0].maps[MATERIAL_MAP_OCCLUSION].value = 1.0f;
|
floor.materials[0].maps[MATERIAL_MAP_OCCLUSION].value = 1.0f;
|
||||||
floor.materials[0].maps[MATERIAL_MAP_EMISSION].color = BLACK;
|
floor.materials[0].maps[MATERIAL_MAP_EMISSION].color = BLACK;
|
||||||
|
|
||||||
@ -229,6 +231,10 @@ int main()
|
|||||||
Vector4 floorEmissiveColor = ColorNormalize(floor.materials[0].maps[MATERIAL_MAP_EMISSION].color);
|
Vector4 floorEmissiveColor = ColorNormalize(floor.materials[0].maps[MATERIAL_MAP_EMISSION].color);
|
||||||
SetShaderValue(shader, emissiveColorLoc, &floorEmissiveColor, SHADER_UNIFORM_VEC4);
|
SetShaderValue(shader, emissiveColorLoc, &floorEmissiveColor, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
// Set floor metallic and roughness values
|
||||||
|
SetShaderValue(shader, metallicValueLoc, &floor.materials[0].maps[MATERIAL_MAP_METALNESS].value, SHADER_UNIFORM_FLOAT);
|
||||||
|
SetShaderValue(shader, roughnessValueLoc, &floor.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value, SHADER_UNIFORM_FLOAT);
|
||||||
|
|
||||||
DrawModel(floor, (Vector3){ 0.0f, 0.0f, 0.0f }, 5.0f, WHITE); // Draw floor model
|
DrawModel(floor, (Vector3){ 0.0f, 0.0f, 0.0f }, 5.0f, WHITE); // Draw floor model
|
||||||
|
|
||||||
// Set old car model texture tiling, emissive color and emissive intensity parameters on shader
|
// Set old car model texture tiling, emissive color and emissive intensity parameters on shader
|
||||||
@ -238,6 +244,10 @@ int main()
|
|||||||
float emissiveIntensity = 0.01f;
|
float emissiveIntensity = 0.01f;
|
||||||
SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, SHADER_UNIFORM_FLOAT);
|
SetShaderValue(shader, emissiveIntensityLoc, &emissiveIntensity, SHADER_UNIFORM_FLOAT);
|
||||||
|
|
||||||
|
// Set old car metallic and roughness values
|
||||||
|
SetShaderValue(shader, metallicValueLoc, &car.materials[0].maps[MATERIAL_MAP_METALNESS].value, SHADER_UNIFORM_FLOAT);
|
||||||
|
SetShaderValue(shader, roughnessValueLoc, &car.materials[0].maps[MATERIAL_MAP_ROUGHNESS].value, SHADER_UNIFORM_FLOAT);
|
||||||
|
|
||||||
DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.25f, WHITE); // Draw car model
|
DrawModel(car, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.25f, WHITE); // Draw car model
|
||||||
|
|
||||||
// Draw spheres to show the lights positions
|
// Draw spheres to show the lights positions
|
||||||
|
@ -52,6 +52,8 @@ int main(void)
|
|||||||
DrawCircle(screenWidth/5, 120, 35, DARKBLUE);
|
DrawCircle(screenWidth/5, 120, 35, DARKBLUE);
|
||||||
DrawCircleGradient(screenWidth/5, 220, 60, GREEN, SKYBLUE);
|
DrawCircleGradient(screenWidth/5, 220, 60, GREEN, SKYBLUE);
|
||||||
DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE);
|
DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE);
|
||||||
|
DrawEllipse(screenWidth/5, 120, 25, 20, YELLOW);
|
||||||
|
DrawEllipseLines(screenWidth/5, 120, 30, 25, YELLOW);
|
||||||
|
|
||||||
// Rectangle shapes and lines
|
// Rectangle shapes and lines
|
||||||
DrawRectangle(screenWidth/4*2 - 60, 100, 120, 60, RED);
|
DrawRectangle(screenWidth/4*2 - 60, 100, 120, 60, RED);
|
||||||
|
185
examples/shapes/shapes_digital_clock.c
Normal file
185
examples/shapes/shapes_digital_clock.c
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [shapes] example - fancy clock using basic shapes
|
||||||
|
*
|
||||||
|
* Example complexity rating: [★★☆☆] 2/4
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||||
|
*
|
||||||
|
* Example contributed by Hamza RAHAL (@hmz-rhl) 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) 2025 Hamza RAHAL (@hmz-rhl)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include <math.h> // Required for: cosf(), sinf()
|
||||||
|
#include <time.h> // Required for: time(), localtime()
|
||||||
|
|
||||||
|
#define DIGIT_SIZE 30
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
typedef enum {
|
||||||
|
MODE_NORMAL = 0,
|
||||||
|
MODE_HANDS_FREE,
|
||||||
|
} ClockMode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int value;
|
||||||
|
Vector2 origin;
|
||||||
|
float angle;
|
||||||
|
int length;
|
||||||
|
int thickness;
|
||||||
|
Color color;
|
||||||
|
} ClockHand;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ClockMode mode;
|
||||||
|
ClockHand second;
|
||||||
|
ClockHand minute;
|
||||||
|
ClockHand hour;
|
||||||
|
} Clock;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static void UpdateClock(Clock *clock); // Update clock time
|
||||||
|
static void DrawClock(Clock clock, Vector2 centerPos); // Draw clock at desired position
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - digital clock");
|
||||||
|
|
||||||
|
// Initialize clock
|
||||||
|
Clock myClock = {
|
||||||
|
.mode = MODE_NORMAL,
|
||||||
|
|
||||||
|
.second.angle = 45,
|
||||||
|
.second.length = 140,
|
||||||
|
.second.thickness = 3,
|
||||||
|
.second.color = BEIGE,
|
||||||
|
|
||||||
|
.minute.angle = 10,
|
||||||
|
.minute.length = 130,
|
||||||
|
.minute.thickness = 7,
|
||||||
|
.minute.color = DARKGRAY,
|
||||||
|
|
||||||
|
.hour.angle = 0,
|
||||||
|
.hour.length = 100,
|
||||||
|
.hour.thickness = 7,
|
||||||
|
.hour.color = BLACK,
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if (IsKeyPressed(KEY_SPACE))
|
||||||
|
{
|
||||||
|
if (myClock.mode == MODE_HANDS_FREE) myClock.mode = MODE_NORMAL;
|
||||||
|
else if (myClock.mode == MODE_NORMAL) myClock.mode = MODE_HANDS_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateClock(&myClock);
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
DrawCircle(400, 225, 5, BLACK); // Clock center dot
|
||||||
|
|
||||||
|
DrawClock(myClock, (Vector2){ 400, 225 }); // Clock in selected mode
|
||||||
|
|
||||||
|
DrawText("Press [SPACE] to switch clock mode", 10, 10, 20, DARKGRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Update clock time
|
||||||
|
static void UpdateClock(Clock *clock)
|
||||||
|
{
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm * timeinfo;
|
||||||
|
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
|
// Updating time data
|
||||||
|
clock->second.value = timeinfo->tm_sec;
|
||||||
|
clock->minute.value = timeinfo->tm_min;
|
||||||
|
clock->hour.value = timeinfo->tm_hour;
|
||||||
|
|
||||||
|
clock->hour.angle = (timeinfo->tm_hour%12)*180.0/6.0f;
|
||||||
|
clock->hour.angle += (timeinfo->tm_min%60)*30/60.0f;
|
||||||
|
clock->hour.angle -= 90;
|
||||||
|
|
||||||
|
clock->minute.angle = (timeinfo->tm_min%60)*6.0f;
|
||||||
|
clock->minute.angle += (timeinfo->tm_sec%60)*6/60.0f;
|
||||||
|
clock->minute.angle -= 90;
|
||||||
|
|
||||||
|
clock->second.angle = (timeinfo->tm_sec%60)*6.0f;
|
||||||
|
clock->second.angle -= 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw clock
|
||||||
|
static void DrawClock(Clock clock, Vector2 centerPosition)
|
||||||
|
{
|
||||||
|
if (clock.mode == MODE_HANDS_FREE)
|
||||||
|
{
|
||||||
|
DrawCircleLinesV(centerPosition, clock.minute.length, LIGHTGRAY);
|
||||||
|
|
||||||
|
DrawText(TextFormat("%i", clock.second.value), centerPosition.x + (clock.second.length - 10)*cosf(clock.second.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.second.length*sinf(clock.second.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, GRAY);
|
||||||
|
|
||||||
|
DrawText(TextFormat("%i", clock.minute.value), clock.minute.origin.x + clock.minute.length*cosf(clock.minute.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.minute.length*sinf(clock.minute.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, RED);
|
||||||
|
|
||||||
|
DrawText(TextFormat("%i", clock.hour.value), centerPosition.x + clock.hour.length*cosf(clock.hour.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.hour.length*sinf(clock.hour.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, GOLD);
|
||||||
|
}
|
||||||
|
else if (clock.mode == MODE_NORMAL)
|
||||||
|
{
|
||||||
|
// Draw hand seconds
|
||||||
|
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.second.length, clock.second.thickness },
|
||||||
|
(Vector2){ 0.0f, clock.second.thickness/2.0f }, clock.second.angle, clock.second.color);
|
||||||
|
|
||||||
|
// Draw hand minutes
|
||||||
|
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.minute.length, clock.minute.thickness },
|
||||||
|
(Vector2){ 0.0f, clock.minute.thickness/2.0f }, clock.minute.angle, clock.minute.color);
|
||||||
|
|
||||||
|
// Draw hand hours
|
||||||
|
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.hour.length, clock.hour.thickness },
|
||||||
|
(Vector2){ 0.0f, clock.hour.thickness/2.0f }, clock.hour.angle, clock.hour.color);
|
||||||
|
}
|
||||||
|
}
|
BIN
examples/shapes/shapes_digital_clock.png
Normal file
BIN
examples/shapes/shapes_digital_clock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
@ -108,7 +108,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Draw provided text with laoded font, containing all required codepoint glyphs
|
// Draw provided text with loaded font, containing all required codepoint glyphs
|
||||||
DrawTextEx(font, text, (Vector2) { 160, 110 }, 48, 5, BLACK);
|
DrawTextEx(font, text, (Vector2) { 160, 110 }, 48, 5, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2300,7 +2300,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GamepadAxis",
|
"name": "GamepadAxis",
|
||||||
"description": "Gamepad axis",
|
"description": "Gamepad axes",
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
"name": "GAMEPAD_AXIS_LEFT_X",
|
"name": "GAMEPAD_AXIS_LEFT_X",
|
||||||
@ -3139,7 +3139,7 @@
|
|||||||
"name": "fileName"
|
"name": "fileName"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "char *",
|
"type": "const char *",
|
||||||
"name": "text"
|
"name": "text"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -4409,7 +4409,7 @@
|
|||||||
"name": "fileName"
|
"name": "fileName"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "char *",
|
"type": "const char *",
|
||||||
"name": "text"
|
"name": "text"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -4684,7 +4684,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "EncodeDataBase64",
|
"name": "EncodeDataBase64",
|
||||||
"description": "Encode data to Base64 string, memory must be MemFree()",
|
"description": "Encode data to Base64 string (includes NULL terminator), memory must be MemFree()",
|
||||||
"returnType": "char *",
|
"returnType": "char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -4703,12 +4703,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "DecodeDataBase64",
|
"name": "DecodeDataBase64",
|
||||||
"description": "Decode Base64 string data, memory must be MemFree()",
|
"description": "Decode Base64 string (expected NULL terminated), memory must be MemFree()",
|
||||||
"returnType": "unsigned char *",
|
"returnType": "unsigned char *",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
"type": "const unsigned char *",
|
"type": "const char *",
|
||||||
"name": "data"
|
"name": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "int *",
|
"type": "int *",
|
||||||
@ -5017,7 +5017,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GetGamepadAxisCount",
|
"name": "GetGamepadAxisCount",
|
||||||
"description": "Get gamepad axis count for a gamepad",
|
"description": "Get axis count for a gamepad",
|
||||||
"returnType": "int",
|
"returnType": "int",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -5028,7 +5028,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GetGamepadAxisMovement",
|
"name": "GetGamepadAxisMovement",
|
||||||
"description": "Get axis movement value for a gamepad axis",
|
"description": "Get movement value for a gamepad axis",
|
||||||
"returnType": "float",
|
"returnType": "float",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -5702,6 +5702,29 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "DrawEllipseV",
|
||||||
|
"description": "Draw ellipse (Vector version)",
|
||||||
|
"returnType": "void",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "Vector2",
|
||||||
|
"name": "center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "float",
|
||||||
|
"name": "radiusH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "float",
|
||||||
|
"name": "radiusV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Color",
|
||||||
|
"name": "color"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "DrawEllipseLines",
|
"name": "DrawEllipseLines",
|
||||||
"description": "Draw ellipse outline",
|
"description": "Draw ellipse outline",
|
||||||
@ -5729,6 +5752,29 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "DrawEllipseLinesV",
|
||||||
|
"description": "Draw ellipse outline (Vector version)",
|
||||||
|
"returnType": "void",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "Vector2",
|
||||||
|
"name": "center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "float",
|
||||||
|
"name": "radiusH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "float",
|
||||||
|
"name": "radiusV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Color",
|
||||||
|
"name": "color"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "DrawRing",
|
"name": "DrawRing",
|
||||||
"description": "Draw ring",
|
"description": "Draw ring",
|
||||||
@ -5964,11 +6010,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Color",
|
"type": "Color",
|
||||||
"name": "topRight"
|
"name": "bottomRight"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Color",
|
"type": "Color",
|
||||||
"name": "bottomRight"
|
"name": "topRight"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -8256,7 +8302,7 @@
|
|||||||
"name": "dst"
|
"name": "dst"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Vector2 *",
|
"type": "const Vector2 *",
|
||||||
"name": "points"
|
"name": "points"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -8279,7 +8325,7 @@
|
|||||||
"name": "dst"
|
"name": "dst"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Vector2 *",
|
"type": "const Vector2 *",
|
||||||
"name": "points"
|
"name": "points"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -8483,7 +8529,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "UpdateTexture",
|
"name": "UpdateTexture",
|
||||||
"description": "Update GPU texture with new data",
|
"description": "Update GPU texture with new data (pixels should be able to fill texture)",
|
||||||
"returnType": "void",
|
"returnType": "void",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -8498,7 +8544,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "UpdateTextureRec",
|
"name": "UpdateTextureRec",
|
||||||
"description": "Update GPU texture rectangle with new data",
|
"description": "Update GPU texture rectangle with new data (pixels and rec should fit in texture)",
|
||||||
"returnType": "void",
|
"returnType": "void",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -11465,7 +11511,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "UpdateSound",
|
"name": "UpdateSound",
|
||||||
"description": "Update sound buffer with new data",
|
"description": "Update sound buffer with new data (data and frame count should fit in sound)",
|
||||||
"returnType": "void",
|
"returnType": "void",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
|
@ -2300,7 +2300,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "GamepadAxis",
|
name = "GamepadAxis",
|
||||||
description = "Gamepad axis",
|
description = "Gamepad axes",
|
||||||
values = {
|
values = {
|
||||||
{
|
{
|
||||||
name = "GAMEPAD_AXIS_LEFT_X",
|
name = "GAMEPAD_AXIS_LEFT_X",
|
||||||
@ -3108,7 +3108,7 @@ return {
|
|||||||
returnType = "bool",
|
returnType = "bool",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "fileName"},
|
{type = "const char *", name = "fileName"},
|
||||||
{type = "char *", name = "text"}
|
{type = "const char *", name = "text"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4006,7 +4006,7 @@ return {
|
|||||||
returnType = "bool",
|
returnType = "bool",
|
||||||
params = {
|
params = {
|
||||||
{type = "const char *", name = "fileName"},
|
{type = "const char *", name = "fileName"},
|
||||||
{type = "char *", name = "text"}
|
{type = "const char *", name = "text"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4198,7 +4198,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "EncodeDataBase64",
|
name = "EncodeDataBase64",
|
||||||
description = "Encode data to Base64 string, memory must be MemFree()",
|
description = "Encode data to Base64 string (includes NULL terminator), memory must be MemFree()",
|
||||||
returnType = "char *",
|
returnType = "char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "const unsigned char *", name = "data"},
|
{type = "const unsigned char *", name = "data"},
|
||||||
@ -4208,10 +4208,10 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "DecodeDataBase64",
|
name = "DecodeDataBase64",
|
||||||
description = "Decode Base64 string data, memory must be MemFree()",
|
description = "Decode Base64 string (expected NULL terminated), memory must be MemFree()",
|
||||||
returnType = "unsigned char *",
|
returnType = "unsigned char *",
|
||||||
params = {
|
params = {
|
||||||
{type = "const unsigned char *", name = "data"},
|
{type = "const char *", name = "text"},
|
||||||
{type = "int *", name = "outputSize"}
|
{type = "int *", name = "outputSize"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4426,7 +4426,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "GetGamepadAxisCount",
|
name = "GetGamepadAxisCount",
|
||||||
description = "Get gamepad axis count for a gamepad",
|
description = "Get axis count for a gamepad",
|
||||||
returnType = "int",
|
returnType = "int",
|
||||||
params = {
|
params = {
|
||||||
{type = "int", name = "gamepad"}
|
{type = "int", name = "gamepad"}
|
||||||
@ -4434,7 +4434,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "GetGamepadAxisMovement",
|
name = "GetGamepadAxisMovement",
|
||||||
description = "Get axis movement value for a gamepad axis",
|
description = "Get movement value for a gamepad axis",
|
||||||
returnType = "float",
|
returnType = "float",
|
||||||
params = {
|
params = {
|
||||||
{type = "int", name = "gamepad"},
|
{type = "int", name = "gamepad"},
|
||||||
@ -4838,6 +4838,17 @@ return {
|
|||||||
{type = "Color", name = "color"}
|
{type = "Color", name = "color"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name = "DrawEllipseV",
|
||||||
|
description = "Draw ellipse (Vector version)",
|
||||||
|
returnType = "void",
|
||||||
|
params = {
|
||||||
|
{type = "Vector2", name = "center"},
|
||||||
|
{type = "float", name = "radiusH"},
|
||||||
|
{type = "float", name = "radiusV"},
|
||||||
|
{type = "Color", name = "color"}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name = "DrawEllipseLines",
|
name = "DrawEllipseLines",
|
||||||
description = "Draw ellipse outline",
|
description = "Draw ellipse outline",
|
||||||
@ -4850,6 +4861,17 @@ return {
|
|||||||
{type = "Color", name = "color"}
|
{type = "Color", name = "color"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name = "DrawEllipseLinesV",
|
||||||
|
description = "Draw ellipse outline (Vector version)",
|
||||||
|
returnType = "void",
|
||||||
|
params = {
|
||||||
|
{type = "Vector2", name = "center"},
|
||||||
|
{type = "float", name = "radiusH"},
|
||||||
|
{type = "float", name = "radiusV"},
|
||||||
|
{type = "Color", name = "color"}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name = "DrawRing",
|
name = "DrawRing",
|
||||||
description = "Draw ring",
|
description = "Draw ring",
|
||||||
@ -4954,8 +4976,8 @@ return {
|
|||||||
{type = "Rectangle", name = "rec"},
|
{type = "Rectangle", name = "rec"},
|
||||||
{type = "Color", name = "topLeft"},
|
{type = "Color", name = "topLeft"},
|
||||||
{type = "Color", name = "bottomLeft"},
|
{type = "Color", name = "bottomLeft"},
|
||||||
{type = "Color", name = "topRight"},
|
{type = "Color", name = "bottomRight"},
|
||||||
{type = "Color", name = "bottomRight"}
|
{type = "Color", name = "topRight"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -6119,7 +6141,7 @@ return {
|
|||||||
returnType = "void",
|
returnType = "void",
|
||||||
params = {
|
params = {
|
||||||
{type = "Image *", name = "dst"},
|
{type = "Image *", name = "dst"},
|
||||||
{type = "Vector2 *", name = "points"},
|
{type = "const Vector2 *", name = "points"},
|
||||||
{type = "int", name = "pointCount"},
|
{type = "int", name = "pointCount"},
|
||||||
{type = "Color", name = "color"}
|
{type = "Color", name = "color"}
|
||||||
}
|
}
|
||||||
@ -6130,7 +6152,7 @@ return {
|
|||||||
returnType = "void",
|
returnType = "void",
|
||||||
params = {
|
params = {
|
||||||
{type = "Image *", name = "dst"},
|
{type = "Image *", name = "dst"},
|
||||||
{type = "Vector2 *", name = "points"},
|
{type = "const Vector2 *", name = "points"},
|
||||||
{type = "int", name = "pointCount"},
|
{type = "int", name = "pointCount"},
|
||||||
{type = "Color", name = "color"}
|
{type = "Color", name = "color"}
|
||||||
}
|
}
|
||||||
@ -6242,7 +6264,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "UpdateTexture",
|
name = "UpdateTexture",
|
||||||
description = "Update GPU texture with new data",
|
description = "Update GPU texture with new data (pixels should be able to fill texture)",
|
||||||
returnType = "void",
|
returnType = "void",
|
||||||
params = {
|
params = {
|
||||||
{type = "Texture2D", name = "texture"},
|
{type = "Texture2D", name = "texture"},
|
||||||
@ -6251,7 +6273,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "UpdateTextureRec",
|
name = "UpdateTextureRec",
|
||||||
description = "Update GPU texture rectangle with new data",
|
description = "Update GPU texture rectangle with new data (pixels and rec should fit in texture)",
|
||||||
returnType = "void",
|
returnType = "void",
|
||||||
params = {
|
params = {
|
||||||
{type = "Texture2D", name = "texture"},
|
{type = "Texture2D", name = "texture"},
|
||||||
@ -7850,7 +7872,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "UpdateSound",
|
name = "UpdateSound",
|
||||||
description = "Update sound buffer with new data",
|
description = "Update sound buffer with new data (data and frame count should fit in sound)",
|
||||||
returnType = "void",
|
returnType = "void",
|
||||||
params = {
|
params = {
|
||||||
{type = "Sound", name = "sound"},
|
{type = "Sound", name = "sound"},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -486,7 +486,7 @@
|
|||||||
<Value name="GAMEPAD_BUTTON_LEFT_THUMB" integer="16" desc="Gamepad joystick pressed button left" />
|
<Value name="GAMEPAD_BUTTON_LEFT_THUMB" integer="16" desc="Gamepad joystick pressed button left" />
|
||||||
<Value name="GAMEPAD_BUTTON_RIGHT_THUMB" integer="17" desc="Gamepad joystick pressed button right" />
|
<Value name="GAMEPAD_BUTTON_RIGHT_THUMB" integer="17" desc="Gamepad joystick pressed button right" />
|
||||||
</Enum>
|
</Enum>
|
||||||
<Enum name="GamepadAxis" valueCount="6" desc="Gamepad axis">
|
<Enum name="GamepadAxis" valueCount="6" desc="Gamepad axes">
|
||||||
<Value name="GAMEPAD_AXIS_LEFT_X" integer="0" desc="Gamepad left stick X axis" />
|
<Value name="GAMEPAD_AXIS_LEFT_X" integer="0" desc="Gamepad left stick X axis" />
|
||||||
<Value name="GAMEPAD_AXIS_LEFT_Y" integer="1" desc="Gamepad left stick Y axis" />
|
<Value name="GAMEPAD_AXIS_LEFT_Y" integer="1" desc="Gamepad left stick Y axis" />
|
||||||
<Value name="GAMEPAD_AXIS_RIGHT_X" integer="2" desc="Gamepad right stick X axis" />
|
<Value name="GAMEPAD_AXIS_RIGHT_X" integer="2" desc="Gamepad right stick X axis" />
|
||||||
@ -672,14 +672,14 @@
|
|||||||
</Callback>
|
</Callback>
|
||||||
<Callback name="SaveFileTextCallback" retType="bool" paramCount="2" desc="FileIO: Save text data">
|
<Callback name="SaveFileTextCallback" retType="bool" paramCount="2" desc="FileIO: Save text data">
|
||||||
<Param type="const char *" name="fileName" desc="" />
|
<Param type="const char *" name="fileName" desc="" />
|
||||||
<Param type="char *" name="text" desc="" />
|
<Param type="const char *" name="text" desc="" />
|
||||||
</Callback>
|
</Callback>
|
||||||
<Callback name="AudioCallback" retType="void" paramCount="2" desc="">
|
<Callback name="AudioCallback" retType="void" paramCount="2" desc="">
|
||||||
<Param type="void *" name="bufferData" desc="" />
|
<Param type="void *" name="bufferData" desc="" />
|
||||||
<Param type="unsigned int" name="frames" desc="" />
|
<Param type="unsigned int" name="frames" desc="" />
|
||||||
</Callback>
|
</Callback>
|
||||||
</Callbacks>
|
</Callbacks>
|
||||||
<Functions count="582">
|
<Functions count="584">
|
||||||
<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="" />
|
||||||
@ -1046,7 +1046,7 @@
|
|||||||
</Function>
|
</Function>
|
||||||
<Function name="SaveFileText" retType="bool" paramCount="2" desc="Save text data to file (write), string must be '\0' terminated, returns true on success">
|
<Function name="SaveFileText" retType="bool" paramCount="2" desc="Save text data to file (write), string must be '\0' terminated, returns true on success">
|
||||||
<Param type="const char *" name="fileName" desc="" />
|
<Param type="const char *" name="fileName" desc="" />
|
||||||
<Param type="char *" name="text" desc="" />
|
<Param type="const char *" name="text" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="FileExists" retType="bool" paramCount="1" desc="Check if file exists">
|
<Function name="FileExists" retType="bool" paramCount="1" desc="Check if file exists">
|
||||||
<Param type="const char *" name="fileName" desc="" />
|
<Param type="const char *" name="fileName" desc="" />
|
||||||
@ -1123,13 +1123,13 @@
|
|||||||
<Param type="int" name="compDataSize" desc="" />
|
<Param type="int" name="compDataSize" desc="" />
|
||||||
<Param type="int *" name="dataSize" desc="" />
|
<Param type="int *" name="dataSize" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="EncodeDataBase64" retType="char *" paramCount="3" desc="Encode data to Base64 string, memory must be MemFree()">
|
<Function name="EncodeDataBase64" retType="char *" paramCount="3" desc="Encode data to Base64 string (includes NULL terminator), memory must be MemFree()">
|
||||||
<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="" />
|
||||||
<Param type="int *" name="outputSize" desc="" />
|
<Param type="int *" name="outputSize" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="DecodeDataBase64" retType="unsigned char *" paramCount="2" desc="Decode Base64 string data, memory must be MemFree()">
|
<Function name="DecodeDataBase64" retType="unsigned char *" paramCount="2" desc="Decode Base64 string (expected NULL terminated), memory must be MemFree()">
|
||||||
<Param type="const unsigned char *" name="data" desc="" />
|
<Param type="const char *" name="text" 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">
|
<Function name="ComputeCRC32" retType="unsigned int" paramCount="2" desc="Compute CRC32 hash code">
|
||||||
@ -1216,10 +1216,10 @@
|
|||||||
</Function>
|
</Function>
|
||||||
<Function name="GetGamepadButtonPressed" retType="int" paramCount="0" desc="Get the last gamepad button pressed">
|
<Function name="GetGamepadButtonPressed" retType="int" paramCount="0" desc="Get the last gamepad button pressed">
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="GetGamepadAxisCount" retType="int" paramCount="1" desc="Get gamepad axis count for a gamepad">
|
<Function name="GetGamepadAxisCount" retType="int" paramCount="1" desc="Get axis count for a gamepad">
|
||||||
<Param type="int" name="gamepad" desc="" />
|
<Param type="int" name="gamepad" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="GetGamepadAxisMovement" retType="float" paramCount="2" desc="Get axis movement value for a gamepad axis">
|
<Function name="GetGamepadAxisMovement" retType="float" paramCount="2" desc="Get movement value for a gamepad axis">
|
||||||
<Param type="int" name="gamepad" desc="" />
|
<Param type="int" name="gamepad" desc="" />
|
||||||
<Param type="int" name="axis" desc="" />
|
<Param type="int" name="axis" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
@ -1409,6 +1409,12 @@
|
|||||||
<Param type="float" name="radiusV" desc="" />
|
<Param type="float" name="radiusV" desc="" />
|
||||||
<Param type="Color" name="color" desc="" />
|
<Param type="Color" name="color" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
|
<Function name="DrawEllipseV" retType="void" paramCount="4" desc="Draw ellipse (Vector version)">
|
||||||
|
<Param type="Vector2" name="center" desc="" />
|
||||||
|
<Param type="float" name="radiusH" desc="" />
|
||||||
|
<Param type="float" name="radiusV" desc="" />
|
||||||
|
<Param type="Color" name="color" desc="" />
|
||||||
|
</Function>
|
||||||
<Function name="DrawEllipseLines" retType="void" paramCount="5" desc="Draw ellipse outline">
|
<Function name="DrawEllipseLines" retType="void" paramCount="5" desc="Draw ellipse outline">
|
||||||
<Param type="int" name="centerX" desc="" />
|
<Param type="int" name="centerX" desc="" />
|
||||||
<Param type="int" name="centerY" desc="" />
|
<Param type="int" name="centerY" desc="" />
|
||||||
@ -1416,6 +1422,12 @@
|
|||||||
<Param type="float" name="radiusV" desc="" />
|
<Param type="float" name="radiusV" desc="" />
|
||||||
<Param type="Color" name="color" desc="" />
|
<Param type="Color" name="color" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
|
<Function name="DrawEllipseLinesV" retType="void" paramCount="4" desc="Draw ellipse outline (Vector version)">
|
||||||
|
<Param type="Vector2" name="center" desc="" />
|
||||||
|
<Param type="float" name="radiusH" desc="" />
|
||||||
|
<Param type="float" name="radiusV" desc="" />
|
||||||
|
<Param type="Color" name="color" desc="" />
|
||||||
|
</Function>
|
||||||
<Function name="DrawRing" retType="void" paramCount="7" desc="Draw ring">
|
<Function name="DrawRing" retType="void" paramCount="7" desc="Draw ring">
|
||||||
<Param type="Vector2" name="center" desc="" />
|
<Param type="Vector2" name="center" desc="" />
|
||||||
<Param type="float" name="innerRadius" desc="" />
|
<Param type="float" name="innerRadius" desc="" />
|
||||||
@ -1476,8 +1488,8 @@
|
|||||||
<Param type="Rectangle" name="rec" desc="" />
|
<Param type="Rectangle" name="rec" desc="" />
|
||||||
<Param type="Color" name="topLeft" desc="" />
|
<Param type="Color" name="topLeft" desc="" />
|
||||||
<Param type="Color" name="bottomLeft" desc="" />
|
<Param type="Color" name="bottomLeft" desc="" />
|
||||||
<Param type="Color" name="topRight" desc="" />
|
|
||||||
<Param type="Color" name="bottomRight" desc="" />
|
<Param type="Color" name="bottomRight" desc="" />
|
||||||
|
<Param type="Color" name="topRight" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="DrawRectangleLines" retType="void" paramCount="5" desc="Draw rectangle outline">
|
<Function name="DrawRectangleLines" retType="void" paramCount="5" desc="Draw rectangle outline">
|
||||||
<Param type="int" name="posX" desc="" />
|
<Param type="int" name="posX" desc="" />
|
||||||
@ -2078,13 +2090,13 @@
|
|||||||
</Function>
|
</Function>
|
||||||
<Function name="ImageDrawTriangleFan" retType="void" paramCount="4" desc="Draw a triangle fan defined by points within an image (first vertex is the center)">
|
<Function name="ImageDrawTriangleFan" retType="void" paramCount="4" desc="Draw a triangle fan defined by points within an image (first vertex is the center)">
|
||||||
<Param type="Image *" name="dst" desc="" />
|
<Param type="Image *" name="dst" desc="" />
|
||||||
<Param type="Vector2 *" name="points" desc="" />
|
<Param type="const Vector2 *" name="points" desc="" />
|
||||||
<Param type="int" name="pointCount" desc="" />
|
<Param type="int" name="pointCount" desc="" />
|
||||||
<Param type="Color" name="color" desc="" />
|
<Param type="Color" name="color" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="ImageDrawTriangleStrip" retType="void" paramCount="4" desc="Draw a triangle strip defined by points within an image">
|
<Function name="ImageDrawTriangleStrip" retType="void" paramCount="4" desc="Draw a triangle strip defined by points within an image">
|
||||||
<Param type="Image *" name="dst" desc="" />
|
<Param type="Image *" name="dst" desc="" />
|
||||||
<Param type="Vector2 *" name="points" desc="" />
|
<Param type="const Vector2 *" name="points" desc="" />
|
||||||
<Param type="int" name="pointCount" desc="" />
|
<Param type="int" name="pointCount" desc="" />
|
||||||
<Param type="Color" name="color" desc="" />
|
<Param type="Color" name="color" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
@ -2138,11 +2150,11 @@
|
|||||||
<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)">
|
||||||
<Param type="RenderTexture2D" name="target" desc="" />
|
<Param type="RenderTexture2D" name="target" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="UpdateTexture" retType="void" paramCount="2" desc="Update GPU texture with new data">
|
<Function name="UpdateTexture" retType="void" paramCount="2" desc="Update GPU texture with new data (pixels should be able to fill texture)">
|
||||||
<Param type="Texture2D" name="texture" desc="" />
|
<Param type="Texture2D" name="texture" desc="" />
|
||||||
<Param type="const void *" name="pixels" desc="" />
|
<Param type="const void *" name="pixels" desc="" />
|
||||||
</Function>
|
</Function>
|
||||||
<Function name="UpdateTextureRec" retType="void" paramCount="3" desc="Update GPU texture rectangle with new data">
|
<Function name="UpdateTextureRec" retType="void" paramCount="3" desc="Update GPU texture rectangle with new data (pixels and rec should fit in texture)">
|
||||||
<Param type="Texture2D" name="texture" desc="" />
|
<Param type="Texture2D" name="texture" desc="" />
|
||||||
<Param type="Rectangle" name="rec" desc="" />
|
<Param type="Rectangle" name="rec" desc="" />
|
||||||
<Param type="const void *" name="pixels" desc="" />
|
<Param type="const void *" name="pixels" desc="" />
|
||||||
@ -2928,7 +2940,7 @@
|
|||||||
<Function name="IsSoundValid" retType="bool" paramCount="1" desc="Checks if a sound is valid (data loaded and buffers initialized)">
|
<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 (data and frame count should fit in sound)">
|
||||||
<Param type="Sound" name="sound" desc="" />
|
<Param type="Sound" name="sound" desc="" />
|
||||||
<Param type="const void *" name="data" desc="" />
|
<Param type="const void *" name="data" desc="" />
|
||||||
<Param type="int" name="sampleCount" desc="" />
|
<Param type="int" name="sampleCount" desc="" />
|
||||||
|
@ -440,8 +440,8 @@ RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color c
|
|||||||
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
|
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
|
||||||
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
|
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
|
||||||
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
|
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
|
||||||
RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
|
RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
|
||||||
RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
|
RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
|
||||||
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
|
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
|
||||||
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
|
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
|
||||||
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
|
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
|
||||||
|
@ -868,7 +868,7 @@ clean: clean_shell_$(PLATFORM_SHELL)
|
|||||||
@echo "removed all generated files!"
|
@echo "removed all generated files!"
|
||||||
|
|
||||||
clean_shell_sh:
|
clean_shell_sh:
|
||||||
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h
|
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||||
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
|
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
|
||||||
endif
|
endif
|
||||||
@ -879,6 +879,7 @@ clean_shell_cmd:
|
|||||||
del *.o /s
|
del *.o /s
|
||||||
cd $(RAYLIB_RELEASE_PATH) & \
|
cd $(RAYLIB_RELEASE_PATH) & \
|
||||||
del lib$(RAYLIB_LIB_NAME).a /s & \
|
del lib$(RAYLIB_LIB_NAME).a /s & \
|
||||||
|
del lib$(RAYLIB_LIB_NAME).web.a /s & \
|
||||||
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
|
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
|
||||||
del $(RAYLIB_LIB_NAME).dll /s & \
|
del $(RAYLIB_LIB_NAME).dll /s & \
|
||||||
del raygui.c /s & \
|
del raygui.c /s & \
|
||||||
|
@ -104,7 +104,7 @@
|
|||||||
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
||||||
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
||||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
#define MAX_GAMEPAD_AXES 8 // Maximum number of axes supported (per gamepad)
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||||
#define MAX_GAMEPAD_VIBRATION_TIME 2.0f // Maximum vibration time in seconds
|
#define MAX_GAMEPAD_VIBRATION_TIME 2.0f // Maximum vibration time in seconds
|
||||||
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||||
@ -189,7 +189,7 @@
|
|||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module: rtextures - Configuration Flags
|
// Module: rtextures - Configuration Flags
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Selecte desired fileformats to be supported for image data loading
|
// Selected desired fileformats to be supported for image data loading
|
||||||
#define SUPPORT_FILEFORMAT_PNG 1
|
#define SUPPORT_FILEFORMAT_PNG 1
|
||||||
//#define SUPPORT_FILEFORMAT_BMP 1
|
//#define SUPPORT_FILEFORMAT_BMP 1
|
||||||
//#define SUPPORT_FILEFORMAT_TGA 1
|
//#define SUPPORT_FILEFORMAT_TGA 1
|
||||||
|
4841
src/external/RGFW.h
vendored
4841
src/external/RGFW.h
vendored
File diff suppressed because it is too large
Load Diff
420
src/external/dr_flac.h
vendored
420
src/external/dr_flac.h
vendored
@ -1,121 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_flac - v0.12.42 - 2023-11-02
|
dr_flac - v0.13.0 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
GitHub: https://github.com/mackron/dr_libs
|
GitHub: https://github.com/mackron/dr_libs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
RELEASE NOTES - v0.12.0
|
|
||||||
=======================
|
|
||||||
Version 0.12.0 has breaking API changes including changes to the existing API and the removal of deprecated APIs.
|
|
||||||
|
|
||||||
|
|
||||||
Improved Client-Defined Memory Allocation
|
|
||||||
-----------------------------------------
|
|
||||||
The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
|
|
||||||
existing system of DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE are still in place and will be used by default when no custom
|
|
||||||
allocation callbacks are specified.
|
|
||||||
|
|
||||||
To use the new system, you pass in a pointer to a drflac_allocation_callbacks object to drflac_open() and family, like this:
|
|
||||||
|
|
||||||
void* my_malloc(size_t sz, void* pUserData)
|
|
||||||
{
|
|
||||||
return malloc(sz);
|
|
||||||
}
|
|
||||||
void* my_realloc(void* p, size_t sz, void* pUserData)
|
|
||||||
{
|
|
||||||
return realloc(p, sz);
|
|
||||||
}
|
|
||||||
void my_free(void* p, void* pUserData)
|
|
||||||
{
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
drflac_allocation_callbacks allocationCallbacks;
|
|
||||||
allocationCallbacks.pUserData = &myData;
|
|
||||||
allocationCallbacks.onMalloc = my_malloc;
|
|
||||||
allocationCallbacks.onRealloc = my_realloc;
|
|
||||||
allocationCallbacks.onFree = my_free;
|
|
||||||
drflac* pFlac = drflac_open_file("my_file.flac", &allocationCallbacks);
|
|
||||||
|
|
||||||
The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
|
|
||||||
|
|
||||||
Passing in null for the allocation callbacks object will cause dr_flac to use defaults which is the same as DRFLAC_MALLOC,
|
|
||||||
DRFLAC_REALLOC and DRFLAC_FREE and the equivalent of how it worked in previous versions.
|
|
||||||
|
|
||||||
Every API that opens a drflac object now takes this extra parameter. These include the following:
|
|
||||||
|
|
||||||
drflac_open()
|
|
||||||
drflac_open_relaxed()
|
|
||||||
drflac_open_with_metadata()
|
|
||||||
drflac_open_with_metadata_relaxed()
|
|
||||||
drflac_open_file()
|
|
||||||
drflac_open_file_with_metadata()
|
|
||||||
drflac_open_memory()
|
|
||||||
drflac_open_memory_with_metadata()
|
|
||||||
drflac_open_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_and_read_pcm_frames_f32()
|
|
||||||
drflac_open_file_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_file_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_file_and_read_pcm_frames_f32()
|
|
||||||
drflac_open_memory_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_memory_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_memory_and_read_pcm_frames_f32()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Optimizations
|
|
||||||
-------------
|
|
||||||
Seeking performance has been greatly improved. A new binary search based seeking algorithm has been introduced which significantly
|
|
||||||
improves performance over the brute force method which was used when no seek table was present. Seek table based seeking also takes
|
|
||||||
advantage of the new binary search seeking system to further improve performance there as well. Note that this depends on CRC which
|
|
||||||
means it will be disabled when DR_FLAC_NO_CRC is used.
|
|
||||||
|
|
||||||
The SSE4.1 pipeline has been cleaned up and optimized. You should see some improvements with decoding speed of 24-bit files in
|
|
||||||
particular. 16-bit streams should also see some improvement.
|
|
||||||
|
|
||||||
drflac_read_pcm_frames_s16() has been optimized. Previously this sat on top of drflac_read_pcm_frames_s32() and performed it's s32
|
|
||||||
to s16 conversion in a second pass. This is now all done in a single pass. This includes SSE2 and ARM NEON optimized paths.
|
|
||||||
|
|
||||||
A minor optimization has been implemented for drflac_read_pcm_frames_s32(). This will now use an SSE2 optimized pipeline for stereo
|
|
||||||
channel reconstruction which is the last part of the decoding process.
|
|
||||||
|
|
||||||
The ARM build has seen a few improvements. The CLZ (count leading zeroes) and REV (byte swap) instructions are now used when
|
|
||||||
compiling with GCC and Clang which is achieved using inline assembly. The CLZ instruction requires ARM architecture version 5 at
|
|
||||||
compile time and the REV instruction requires ARM architecture version 6.
|
|
||||||
|
|
||||||
An ARM NEON optimized pipeline has been implemented. To enable this you'll need to add -mfpu=neon to the command line when compiling.
|
|
||||||
|
|
||||||
|
|
||||||
Removed APIs
|
|
||||||
------------
|
|
||||||
The following APIs were deprecated in version 0.11.0 and have been completely removed in version 0.12.0:
|
|
||||||
|
|
||||||
drflac_read_s32() -> drflac_read_pcm_frames_s32()
|
|
||||||
drflac_read_s16() -> drflac_read_pcm_frames_s16()
|
|
||||||
drflac_read_f32() -> drflac_read_pcm_frames_f32()
|
|
||||||
drflac_seek_to_sample() -> drflac_seek_to_pcm_frame()
|
|
||||||
drflac_open_and_decode_s32() -> drflac_open_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_and_decode_s16() -> drflac_open_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_and_decode_f32() -> drflac_open_and_read_pcm_frames_f32()
|
|
||||||
drflac_open_and_decode_file_s32() -> drflac_open_file_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_and_decode_file_s16() -> drflac_open_file_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_and_decode_file_f32() -> drflac_open_file_and_read_pcm_frames_f32()
|
|
||||||
drflac_open_and_decode_memory_s32() -> drflac_open_memory_and_read_pcm_frames_s32()
|
|
||||||
drflac_open_and_decode_memory_s16() -> drflac_open_memory_and_read_pcm_frames_s16()
|
|
||||||
drflac_open_and_decode_memory_f32() -> drflac_open_memroy_and_read_pcm_frames_f32()
|
|
||||||
|
|
||||||
Prior versions of dr_flac operated on a per-sample basis whereas now it operates on PCM frames. The removed APIs all relate
|
|
||||||
to the old per-sample APIs. You now need to use the "pcm_frame" versions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
@ -234,8 +125,8 @@ extern "C" {
|
|||||||
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
||||||
|
|
||||||
#define DRFLAC_VERSION_MAJOR 0
|
#define DRFLAC_VERSION_MAJOR 0
|
||||||
#define DRFLAC_VERSION_MINOR 12
|
#define DRFLAC_VERSION_MINOR 13
|
||||||
#define DRFLAC_VERSION_REVISION 42
|
#define DRFLAC_VERSION_REVISION 0
|
||||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
@ -348,11 +239,11 @@ but also more memory. In my testing there is diminishing returns after about 4KB
|
|||||||
#define DRFLAC_64BIT
|
#define DRFLAC_64BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__x86_64__) || defined(_M_X64)
|
#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
||||||
#define DRFLAC_X64
|
#define DRFLAC_X64
|
||||||
#elif defined(__i386) || defined(_M_IX86)
|
#elif defined(__i386) || defined(_M_IX86)
|
||||||
#define DRFLAC_X86
|
#define DRFLAC_X86
|
||||||
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
|
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||||
#define DRFLAC_ARM
|
#define DRFLAC_ARM
|
||||||
#endif
|
#endif
|
||||||
/* End Architecture Detection */
|
/* End Architecture Detection */
|
||||||
@ -406,8 +297,9 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
drflac_seek_origin_start,
|
DRFLAC_SEEK_SET,
|
||||||
drflac_seek_origin_current
|
DRFLAC_SEEK_CUR,
|
||||||
|
DRFLAC_SEEK_END
|
||||||
} drflac_seek_origin;
|
} drflac_seek_origin;
|
||||||
|
|
||||||
/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
|
/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
|
||||||
@ -547,7 +439,7 @@ offset (in)
|
|||||||
The number of bytes to move, relative to the origin. Will never be negative.
|
The number of bytes to move, relative to the origin. Will never be negative.
|
||||||
|
|
||||||
origin (in)
|
origin (in)
|
||||||
The origin of the seek - the current position or the start of the stream.
|
The origin of the seek - the current position, the start of the stream, or the end of the stream.
|
||||||
|
|
||||||
|
|
||||||
Return Value
|
Return Value
|
||||||
@ -557,14 +449,32 @@ Whether or not the seek was successful.
|
|||||||
|
|
||||||
Remarks
|
Remarks
|
||||||
-------
|
-------
|
||||||
The offset will never be negative. Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be
|
Seeking relative to the start and the current position must always be supported. If seeking from the end of the stream is not supported, return DRFLAC_FALSE.
|
||||||
either drflac_seek_origin_start or drflac_seek_origin_current.
|
|
||||||
|
|
||||||
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
|
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
|
||||||
and handled by returning DRFLAC_FALSE.
|
and handled by returning DRFLAC_FALSE.
|
||||||
*/
|
*/
|
||||||
typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
|
typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callback for when the current position in the stream needs to be retrieved.
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
pUserData (in)
|
||||||
|
The user data that was passed to drflac_open() and family.
|
||||||
|
|
||||||
|
pCursor (out)
|
||||||
|
A pointer to a variable to receive the current position in the stream.
|
||||||
|
|
||||||
|
|
||||||
|
Return Value
|
||||||
|
------------
|
||||||
|
Whether or not the operation was successful.
|
||||||
|
*/
|
||||||
|
typedef drflac_bool32 (* drflac_tell_proc)(void* pUserData, drflac_int64* pCursor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Callback for when a metadata block is read.
|
Callback for when a metadata block is read.
|
||||||
|
|
||||||
@ -603,6 +513,9 @@ typedef struct
|
|||||||
/* The function to call when the current read position needs to be moved. */
|
/* The function to call when the current read position needs to be moved. */
|
||||||
drflac_seek_proc onSeek;
|
drflac_seek_proc onSeek;
|
||||||
|
|
||||||
|
/* The function to call when the current read position needs to be retrieved. */
|
||||||
|
drflac_tell_proc onTell;
|
||||||
|
|
||||||
/* The user data to pass around to onRead and onSeek. */
|
/* The user data to pass around to onRead and onSeek. */
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
|
|
||||||
@ -828,7 +741,7 @@ drflac_open_memory()
|
|||||||
drflac_open_with_metadata()
|
drflac_open_with_metadata()
|
||||||
drflac_close()
|
drflac_close()
|
||||||
*/
|
*/
|
||||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Opens a FLAC stream with relaxed validation of the header block.
|
Opens a FLAC stream with relaxed validation of the header block.
|
||||||
@ -869,7 +782,7 @@ force your `onRead` callback to return 0, which dr_flac will use as an indicator
|
|||||||
|
|
||||||
Use `drflac_open_with_metadata_relaxed()` if you need access to metadata.
|
Use `drflac_open_with_metadata_relaxed()` if you need access to metadata.
|
||||||
*/
|
*/
|
||||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
|
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
|
||||||
@ -926,7 +839,7 @@ drflac_open_memory_with_metadata()
|
|||||||
drflac_open()
|
drflac_open()
|
||||||
drflac_close()
|
drflac_close()
|
||||||
*/
|
*/
|
||||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
|
The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
|
||||||
@ -936,7 +849,7 @@ See Also
|
|||||||
drflac_open_with_metadata()
|
drflac_open_with_metadata()
|
||||||
drflac_open_relaxed()
|
drflac_open_relaxed()
|
||||||
*/
|
*/
|
||||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Closes the given FLAC decoder.
|
Closes the given FLAC decoder.
|
||||||
@ -1234,13 +1147,13 @@ read samples into a dynamically sized buffer on the heap until no samples are le
|
|||||||
|
|
||||||
Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
|
Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
|
||||||
*/
|
*/
|
||||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
|
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
|
||||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
|
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
|
||||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
#ifndef DR_FLAC_NO_STDIO
|
#ifndef DR_FLAC_NO_STDIO
|
||||||
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
|
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
|
||||||
@ -2960,25 +2873,25 @@ static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFro
|
|||||||
*/
|
*/
|
||||||
if (offsetFromStart > 0x7FFFFFFF) {
|
if (offsetFromStart > 0x7FFFFFFF) {
|
||||||
drflac_uint64 bytesRemaining = offsetFromStart;
|
drflac_uint64 bytesRemaining = offsetFromStart;
|
||||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
bytesRemaining -= 0x7FFFFFFF;
|
bytesRemaining -= 0x7FFFFFFF;
|
||||||
|
|
||||||
while (bytesRemaining > 0x7FFFFFFF) {
|
while (bytesRemaining > 0x7FFFFFFF) {
|
||||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
bytesRemaining -= 0x7FFFFFFF;
|
bytesRemaining -= 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesRemaining > 0) {
|
if (bytesRemaining > 0) {
|
||||||
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
|
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
|
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5393,6 +5306,12 @@ static drflac_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe
|
|||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default to 0 for the LPC order. It's important that we always set this to 0 for non LPC
|
||||||
|
and FIXED subframes because we'll be using it in a generic validation check later.
|
||||||
|
*/
|
||||||
|
pSubframe->lpcOrder = 0;
|
||||||
|
|
||||||
type = (header & 0x7E) >> 1;
|
type = (header & 0x7E) >> 1;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT;
|
pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT;
|
||||||
@ -5465,6 +5384,18 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
|
|||||||
|
|
||||||
pSubframe->pSamplesS32 = pDecodedSamplesOut;
|
pSubframe->pSamplesS32 = pDecodedSamplesOut;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pDecodedSamplesOut will be pointing to a buffer that was allocated with enough memory to store
|
||||||
|
maxBlockSizeInPCMFrames samples (as specified in the FLAC header). We need to guard against an
|
||||||
|
overflow here. At a higher level we are checking maxBlockSizeInPCMFrames from the header, but
|
||||||
|
here we need to do an additional check to ensure this frame's block size fully encompasses any
|
||||||
|
warmup samples which is determined by the LPC order. For non LPC and FIXED subframes, the LPC
|
||||||
|
order will be have been set to 0 in drflac__read_subframe_header().
|
||||||
|
*/
|
||||||
|
if (frame->header.blockSizeInPCMFrames < pSubframe->lpcOrder) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (pSubframe->subframeType)
|
switch (pSubframe->subframeType)
|
||||||
{
|
{
|
||||||
case DRFLAC_SUBFRAME_CONSTANT:
|
case DRFLAC_SUBFRAME_CONSTANT:
|
||||||
@ -6312,6 +6243,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
drflac_read_proc onRead;
|
drflac_read_proc onRead;
|
||||||
drflac_seek_proc onSeek;
|
drflac_seek_proc onSeek;
|
||||||
|
drflac_tell_proc onTell;
|
||||||
drflac_meta_proc onMeta;
|
drflac_meta_proc onMeta;
|
||||||
drflac_container container;
|
drflac_container container;
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
@ -6479,7 +6411,7 @@ static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
|
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
|
||||||
@ -6489,6 +6421,8 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||||||
drflac_uint64 seektablePos = 0;
|
drflac_uint64 seektablePos = 0;
|
||||||
drflac_uint32 seektableSize = 0;
|
drflac_uint32 seektableSize = 0;
|
||||||
|
|
||||||
|
(void)onTell;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
drflac_metadata metadata;
|
drflac_metadata metadata;
|
||||||
drflac_uint8 isLastBlock = 0;
|
drflac_uint8 isLastBlock = 0;
|
||||||
@ -6840,7 +6774,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||||||
metadata.data.padding.unused = 0;
|
metadata.data.padding.unused = 0;
|
||||||
|
|
||||||
/* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */
|
/* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */
|
||||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||||
} else {
|
} else {
|
||||||
onMeta(pUserDataMD, &metadata);
|
onMeta(pUserDataMD, &metadata);
|
||||||
@ -6852,7 +6786,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||||||
{
|
{
|
||||||
/* Invalid chunk. Just skip over this one. */
|
/* Invalid chunk. Just skip over this one. */
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6886,7 +6820,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||||||
|
|
||||||
/* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */
|
/* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */
|
||||||
if (onMeta == NULL && blockSize > 0) {
|
if (onMeta == NULL && blockSize > 0) {
|
||||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||||
isLastBlock = DRFLAC_TRUE;
|
isLastBlock = DRFLAC_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7220,6 +7154,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */
|
drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */
|
||||||
drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */
|
drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */
|
||||||
|
drflac_tell_proc onTell; /* The original onTell callback from drflac_open() and family. */
|
||||||
void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */
|
void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */
|
||||||
drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */
|
drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */
|
||||||
drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */
|
drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */
|
||||||
@ -7241,32 +7176,32 @@ static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut,
|
|||||||
|
|
||||||
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
|
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
|
||||||
{
|
{
|
||||||
if (origin == drflac_seek_origin_start) {
|
if (origin == DRFLAC_SEEK_SET) {
|
||||||
if (offset <= 0x7FFFFFFF) {
|
if (offset <= 0x7FFFFFFF) {
|
||||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
|
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
oggbs->currentBytePos = offset;
|
oggbs->currentBytePos = offset;
|
||||||
|
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
} else {
|
} else {
|
||||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
oggbs->currentBytePos = offset;
|
oggbs->currentBytePos = offset;
|
||||||
|
|
||||||
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
|
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, DRFLAC_SEEK_CUR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (offset > 0x7FFFFFFF) {
|
while (offset > 0x7FFFFFFF) {
|
||||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
oggbs->currentBytePos += 0x7FFFFFFF;
|
oggbs->currentBytePos += 0x7FFFFFFF;
|
||||||
offset -= 0x7FFFFFFF;
|
offset -= 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) { /* <-- Safe cast thanks to the loop above. */
|
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_CUR)) { /* <-- Safe cast thanks to the loop above. */
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
oggbs->currentBytePos += offset;
|
oggbs->currentBytePos += offset;
|
||||||
@ -7298,7 +7233,7 @@ static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs, drflac_og
|
|||||||
|
|
||||||
if (header.serialNumber != oggbs->serialNumber) {
|
if (header.serialNumber != oggbs->serialNumber) {
|
||||||
/* It's not a FLAC page. Skip it. */
|
/* It's not a FLAC page. Skip it. */
|
||||||
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
|
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -7384,7 +7319,7 @@ static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
|
|||||||
At this point we will have found either the packet or the end of the page. If were at the end of the page we'll
|
At this point we will have found either the packet or the end of the page. If were at the end of the page we'll
|
||||||
want to load the next page and keep searching for the end of the packet.
|
want to load the next page and keep searching for the end of the packet.
|
||||||
*/
|
*/
|
||||||
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
|
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, DRFLAC_SEEK_CUR);
|
||||||
oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
|
oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
|
||||||
|
|
||||||
if (atEndOfPage) {
|
if (atEndOfPage) {
|
||||||
@ -7462,8 +7397,8 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||||
|
|
||||||
/* Seeking is always forward which makes things a lot simpler. */
|
/* Seeking is always forward which makes things a lot simpler. */
|
||||||
if (origin == drflac_seek_origin_start) {
|
if (origin == DRFLAC_SEEK_SET) {
|
||||||
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, drflac_seek_origin_start)) {
|
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7471,11 +7406,8 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
|
return drflac__on_seek_ogg(pUserData, offset, DRFLAC_SEEK_CUR);
|
||||||
}
|
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||||
|
|
||||||
DRFLAC_ASSERT(origin == drflac_seek_origin_current);
|
|
||||||
|
|
||||||
while (bytesSeeked < offset) {
|
while (bytesSeeked < offset) {
|
||||||
int bytesRemainingToSeek = offset - bytesSeeked;
|
int bytesRemainingToSeek = offset - bytesSeeked;
|
||||||
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
||||||
@ -7499,10 +7431,25 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (origin == DRFLAC_SEEK_END) {
|
||||||
|
/* Seeking to the end is not supported. */
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static drflac_bool32 drflac__on_tell_ogg(void* pUserData, drflac_int64* pCursor)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Not implemented for Ogg containers because we don't currently track the byte position of the logical bitstream. To support this, we'll need
|
||||||
|
to track the position in drflac__on_read_ogg and drflac__on_seek_ogg.
|
||||||
|
*/
|
||||||
|
(void)pUserData;
|
||||||
|
(void)pCursor;
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
|
static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
|
||||||
{
|
{
|
||||||
@ -7525,7 +7472,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
|||||||
runningGranulePosition = 0;
|
runningGranulePosition = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||||
drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
|
drflac_oggbs__seek_physical(oggbs, originalBytePos, DRFLAC_SEEK_SET);
|
||||||
return DRFLAC_FALSE; /* Never did find that sample... */
|
return DRFLAC_FALSE; /* Never did find that sample... */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7559,7 +7506,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
|||||||
a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
|
a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
|
||||||
we find the one containing the target sample.
|
we find the one containing the target sample.
|
||||||
*/
|
*/
|
||||||
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
|
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, DRFLAC_SEEK_SET)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||||
@ -7726,7 +7673,7 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||||||
The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
|
The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
|
||||||
be handling it in a generic way based on the serial number and packet types.
|
be handling it in a generic way based on the serial number and packet types.
|
||||||
*/
|
*/
|
||||||
if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, 2, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7783,18 +7730,18 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Not a FLAC header. Skip it. */
|
/* Not a FLAC header. Skip it. */
|
||||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Not a FLAC header. Seek past the entire page and move on to the next. */
|
/* Not a FLAC header. Seek past the entire page and move on to the next. */
|
||||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7819,18 +7766,19 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
||||||
{
|
{
|
||||||
drflac_bool32 relaxed;
|
drflac_bool32 relaxed;
|
||||||
drflac_uint8 id[4];
|
drflac_uint8 id[4];
|
||||||
|
|
||||||
if (pInit == NULL || onRead == NULL || onSeek == NULL) {
|
if (pInit == NULL || onRead == NULL || onSeek == NULL) { /* <-- onTell is optional. */
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
|
DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
|
||||||
pInit->onRead = onRead;
|
pInit->onRead = onRead;
|
||||||
pInit->onSeek = onSeek;
|
pInit->onSeek = onSeek;
|
||||||
|
pInit->onTell = onTell;
|
||||||
pInit->onMeta = onMeta;
|
pInit->onMeta = onMeta;
|
||||||
pInit->container = container;
|
pInit->container = container;
|
||||||
pInit->pUserData = pUserData;
|
pInit->pUserData = pUserData;
|
||||||
@ -7838,6 +7786,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
|||||||
|
|
||||||
pInit->bs.onRead = onRead;
|
pInit->bs.onRead = onRead;
|
||||||
pInit->bs.onSeek = onSeek;
|
pInit->bs.onSeek = onSeek;
|
||||||
|
pInit->bs.onTell = onTell;
|
||||||
pInit->bs.pUserData = pUserData;
|
pInit->bs.pUserData = pUserData;
|
||||||
drflac__reset_cache(&pInit->bs);
|
drflac__reset_cache(&pInit->bs);
|
||||||
|
|
||||||
@ -7870,7 +7819,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
|||||||
headerSize += 10;
|
headerSize += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
|
if (!onSeek(pUserData, headerSize, DRFLAC_SEEK_CUR)) {
|
||||||
return DRFLAC_FALSE; /* Failed to seek past the tag. */
|
return DRFLAC_FALSE; /* Failed to seek past the tag. */
|
||||||
}
|
}
|
||||||
pInit->runningFilePos += headerSize;
|
pInit->runningFilePos += headerSize;
|
||||||
@ -7922,7 +7871,7 @@ static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drflac_init_info init;
|
drflac_init_info init;
|
||||||
drflac_uint32 allocationSize;
|
drflac_uint32 allocationSize;
|
||||||
@ -7940,7 +7889,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
/* CPU support first. */
|
/* CPU support first. */
|
||||||
drflac__init_cpu_caps();
|
drflac__init_cpu_caps();
|
||||||
|
|
||||||
if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
|
if (!drflac__init_private(&init, onRead, onSeek, onTell, onMeta, container, pUserData, pUserDataMD)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7996,6 +7945,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
|
DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
|
||||||
pOggbs->onRead = onRead;
|
pOggbs->onRead = onRead;
|
||||||
pOggbs->onSeek = onSeek;
|
pOggbs->onSeek = onSeek;
|
||||||
|
pOggbs->onTell = onTell;
|
||||||
pOggbs->pUserData = pUserData;
|
pOggbs->pUserData = pUserData;
|
||||||
pOggbs->currentBytePos = init.oggFirstBytePos;
|
pOggbs->currentBytePos = init.oggFirstBytePos;
|
||||||
pOggbs->firstBytePos = init.oggFirstBytePos;
|
pOggbs->firstBytePos = init.oggFirstBytePos;
|
||||||
@ -8016,17 +7966,19 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
if (init.hasMetadataBlocks) {
|
if (init.hasMetadataBlocks) {
|
||||||
drflac_read_proc onReadOverride = onRead;
|
drflac_read_proc onReadOverride = onRead;
|
||||||
drflac_seek_proc onSeekOverride = onSeek;
|
drflac_seek_proc onSeekOverride = onSeek;
|
||||||
|
drflac_tell_proc onTellOverride = onTell;
|
||||||
void* pUserDataOverride = pUserData;
|
void* pUserDataOverride = pUserData;
|
||||||
|
|
||||||
#ifndef DR_FLAC_NO_OGG
|
#ifndef DR_FLAC_NO_OGG
|
||||||
if (init.container == drflac_container_ogg) {
|
if (init.container == drflac_container_ogg) {
|
||||||
onReadOverride = drflac__on_read_ogg;
|
onReadOverride = drflac__on_read_ogg;
|
||||||
onSeekOverride = drflac__on_seek_ogg;
|
onSeekOverride = drflac__on_seek_ogg;
|
||||||
|
onTellOverride = drflac__on_tell_ogg;
|
||||||
pUserDataOverride = (void*)pOggbs;
|
pUserDataOverride = (void*)pOggbs;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onTellOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
||||||
#ifndef DR_FLAC_NO_OGG
|
#ifndef DR_FLAC_NO_OGG
|
||||||
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
||||||
#endif
|
#endif
|
||||||
@ -8061,6 +8013,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
/* The Ogg bistream needs to be layered on top of the original bitstream. */
|
/* The Ogg bistream needs to be layered on top of the original bitstream. */
|
||||||
pFlac->bs.onRead = drflac__on_read_ogg;
|
pFlac->bs.onRead = drflac__on_read_ogg;
|
||||||
pFlac->bs.onSeek = drflac__on_seek_ogg;
|
pFlac->bs.onSeek = drflac__on_seek_ogg;
|
||||||
|
pFlac->bs.onTell = drflac__on_tell_ogg;
|
||||||
pFlac->bs.pUserData = (void*)pInternalOggbs;
|
pFlac->bs.pUserData = (void*)pInternalOggbs;
|
||||||
pFlac->_oggbs = (void*)pInternalOggbs;
|
pFlac->_oggbs = (void*)pInternalOggbs;
|
||||||
}
|
}
|
||||||
@ -8087,7 +8040,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
|
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
|
||||||
|
|
||||||
/* Seek to the seektable, then just read directly into our seektable buffer. */
|
/* Seek to the seektable, then just read directly into our seektable buffer. */
|
||||||
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
|
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, DRFLAC_SEEK_SET)) {
|
||||||
drflac_uint32 iSeekpoint;
|
drflac_uint32 iSeekpoint;
|
||||||
|
|
||||||
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
|
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
|
||||||
@ -8105,7 +8058,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We need to seek back to where we were. If this fails it's a critical error. */
|
/* We need to seek back to where we were. If this fails it's a critical error. */
|
||||||
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
|
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, DRFLAC_SEEK_SET)) {
|
||||||
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
|
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -8276,7 +8229,7 @@ static drflac_result drflac_result_from_errno(int e)
|
|||||||
#ifdef ENOSYS
|
#ifdef ENOSYS
|
||||||
case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
|
case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENOTEMPTY
|
#if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST /* In AIX, ENOTEMPTY and EEXIST use the same value. */
|
||||||
case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
|
case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ELOOP
|
#ifdef ELOOP
|
||||||
@ -8727,11 +8680,41 @@ static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t byt
|
|||||||
|
|
||||||
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
||||||
{
|
{
|
||||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
int whence = SEEK_SET;
|
||||||
|
if (origin == DRFLAC_SEEK_CUR) {
|
||||||
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
whence = SEEK_CUR;
|
||||||
|
} else if (origin == DRFLAC_SEEK_END) {
|
||||||
|
whence = SEEK_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fseek((FILE*)pUserData, offset, whence) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCursor)
|
||||||
|
{
|
||||||
|
FILE* pFileStdio = (FILE*)pUserData;
|
||||||
|
drflac_int64 result;
|
||||||
|
|
||||||
|
/* These were all validated at a higher level. */
|
||||||
|
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||||
|
DRFLAC_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
|
result = _ftelli64(pFileStdio);
|
||||||
|
#else
|
||||||
|
result = ftell(pFileStdio);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
result = ftell(pFileStdio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*pCursor = result;
|
||||||
|
|
||||||
|
return DRFLAC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
@ -8742,7 +8725,7 @@ DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocati
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -8761,7 +8744,7 @@ DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_all
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -8780,7 +8763,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return pFlac;
|
return pFlac;
|
||||||
@ -8799,7 +8782,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, dr
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return pFlac;
|
return pFlac;
|
||||||
@ -8834,28 +8817,45 @@ static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t by
|
|||||||
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
|
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
|
||||||
{
|
{
|
||||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||||
|
drflac_int64 newCursor;
|
||||||
|
|
||||||
DRFLAC_ASSERT(memoryStream != NULL);
|
DRFLAC_ASSERT(memoryStream != NULL);
|
||||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
|
||||||
|
|
||||||
if (offset > (drflac_int64)memoryStream->dataSize) {
|
newCursor = memoryStream->currentReadPos;
|
||||||
|
|
||||||
|
if (origin == DRFLAC_SEEK_SET) {
|
||||||
|
newCursor = 0;
|
||||||
|
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||||
|
newCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||||
|
} else if (origin == DRFLAC_SEEK_END) {
|
||||||
|
newCursor = (drflac_int64)memoryStream->dataSize;
|
||||||
|
} else {
|
||||||
|
DRFLAC_ASSERT(!"Invalid seek origin");
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin == drflac_seek_origin_current) {
|
newCursor += offset;
|
||||||
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
|
|
||||||
memoryStream->currentReadPos += offset;
|
if (newCursor < 0) {
|
||||||
} else {
|
return DRFLAC_FALSE; /* Trying to seek prior to the start of the buffer. */
|
||||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((drflac_uint32)offset <= memoryStream->dataSize) {
|
|
||||||
memoryStream->currentReadPos = offset;
|
|
||||||
} else {
|
|
||||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
|
||||||
}
|
}
|
||||||
|
if ((size_t)newCursor > memoryStream->dataSize) {
|
||||||
|
return DRFLAC_FALSE; /* Trying to seek beyond the end of the buffer. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memoryStream->currentReadPos = (size_t)newCursor;
|
||||||
|
|
||||||
|
return DRFLAC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static drflac_bool32 drflac__on_tell_memory(void* pUserData, drflac_int64* pCursor)
|
||||||
|
{
|
||||||
|
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||||
|
|
||||||
|
DRFLAC_ASSERT(memoryStream != NULL);
|
||||||
|
DRFLAC_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
|
*pCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||||
return DRFLAC_TRUE;
|
return DRFLAC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8867,7 +8867,7 @@ DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const
|
|||||||
memoryStream.data = (const drflac_uint8*)pData;
|
memoryStream.data = (const drflac_uint8*)pData;
|
||||||
memoryStream.dataSize = dataSize;
|
memoryStream.dataSize = dataSize;
|
||||||
memoryStream.currentReadPos = 0;
|
memoryStream.currentReadPos = 0;
|
||||||
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
|
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, &memoryStream, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -8898,7 +8898,7 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
|||||||
memoryStream.data = (const drflac_uint8*)pData;
|
memoryStream.data = (const drflac_uint8*)pData;
|
||||||
memoryStream.dataSize = dataSize;
|
memoryStream.dataSize = dataSize;
|
||||||
memoryStream.currentReadPos = 0;
|
memoryStream.currentReadPos = 0;
|
||||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -8923,22 +8923,22 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||||
}
|
}
|
||||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||||
}
|
}
|
||||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRFLAC_API void drflac_close(drflac* pFlac)
|
DRFLAC_API void drflac_close(drflac* pFlac)
|
||||||
@ -11770,7 +11770,7 @@ DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s32, drflac_int32)
|
|||||||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
|
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
|
||||||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
|
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
|
||||||
|
|
||||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drflac* pFlac;
|
drflac* pFlac;
|
||||||
|
|
||||||
@ -11784,7 +11784,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
|||||||
*totalPCMFrameCountOut = 0;
|
*totalPCMFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -11792,7 +11792,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
|||||||
return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drflac* pFlac;
|
drflac* pFlac;
|
||||||
|
|
||||||
@ -11806,7 +11806,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
|||||||
*totalPCMFrameCountOut = 0;
|
*totalPCMFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -11814,7 +11814,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
|||||||
return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drflac* pFlac;
|
drflac* pFlac;
|
||||||
|
|
||||||
@ -11828,7 +11828,7 @@ DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, d
|
|||||||
*totalPCMFrameCountOut = 0;
|
*totalPCMFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -12077,6 +12077,26 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
|||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
|
v0.13.0 - TBD
|
||||||
|
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||||
|
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||||
|
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||||
|
- DRFLAC_SEEK_END (new)
|
||||||
|
- API CHANGE: A new seek origin has been added to allow seeking from the end of the file. If you implement your own `onSeek` callback, you should now detect and handle `DRFLAC_SEEK_END`. If seeking to the end is not supported, return `DRFLAC_FALSE`. If you only use `*_open_file()` or `*_open_memory()`, you need not change anything.
|
||||||
|
- API CHANGE: An `onTell` callback has been added to the following functions:
|
||||||
|
- drflac_open()
|
||||||
|
- drflac_open_relaxed()
|
||||||
|
- drflac_open_with_metadata()
|
||||||
|
- drflac_open_with_metadata_relaxed()
|
||||||
|
- drflac_open_and_read_pcm_frames_s32()
|
||||||
|
- drflac_open_and_read_pcm_frames_s16()
|
||||||
|
- drflac_open_and_read_pcm_frames_f32()
|
||||||
|
- Fix compilation for AIX OS.
|
||||||
|
|
||||||
|
v0.12.43 - 2024-12-17
|
||||||
|
- Fix a possible buffer overflow during decoding.
|
||||||
|
- Improve detection of ARM64EC
|
||||||
|
|
||||||
v0.12.42 - 2023-11-02
|
v0.12.42 - 2023-11-02
|
||||||
- Fix build for ARMv6-M.
|
- Fix build for ARMv6-M.
|
||||||
- Fix a compilation warning with GCC.
|
- Fix a compilation warning with GCC.
|
||||||
|
857
src/external/dr_mp3.h
vendored
857
src/external/dr_mp3.h
vendored
File diff suppressed because it is too large
Load Diff
430
src/external/dr_wav.h
vendored
430
src/external/dr_wav.h
vendored
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_wav - v0.13.16 - 2024-02-27
|
dr_wav - v0.14.0 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
@ -146,8 +146,8 @@ extern "C" {
|
|||||||
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
|
#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
|
||||||
|
|
||||||
#define DRWAV_VERSION_MAJOR 0
|
#define DRWAV_VERSION_MAJOR 0
|
||||||
#define DRWAV_VERSION_MINOR 13
|
#define DRWAV_VERSION_MINOR 14
|
||||||
#define DRWAV_VERSION_REVISION 16
|
#define DRWAV_VERSION_REVISION 0
|
||||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
@ -176,7 +176,7 @@ typedef unsigned int drwav_uint32;
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
|
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__powerpc64__)
|
||||||
typedef drwav_uint64 drwav_uintptr;
|
typedef drwav_uint64 drwav_uintptr;
|
||||||
#else
|
#else
|
||||||
typedef drwav_uint32 drwav_uintptr;
|
typedef drwav_uint32 drwav_uintptr;
|
||||||
@ -305,8 +305,9 @@ typedef struct
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
drwav_seek_origin_start,
|
DRWAV_SEEK_SET,
|
||||||
drwav_seek_origin_current
|
DRWAV_SEEK_CUR,
|
||||||
|
DRWAV_SEEK_END
|
||||||
} drwav_seek_origin;
|
} drwav_seek_origin;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -415,11 +416,21 @@ origin [in] The origin of the seek - the current position or the start of the
|
|||||||
|
|
||||||
Returns whether or not the seek was successful.
|
Returns whether or not the seek was successful.
|
||||||
|
|
||||||
Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be either drwav_seek_origin_start or
|
Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be either DRWAV_SEEK_SET or
|
||||||
drwav_seek_origin_current.
|
DRWAV_SEEK_CUR.
|
||||||
*/
|
*/
|
||||||
typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
|
typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callback for when the current position in the stream needs to be retrieved.
|
||||||
|
|
||||||
|
pUserData [in] The user data that was passed to drwav_init() and family.
|
||||||
|
pCursor [out] A pointer to a variable to receive the current position in the stream.
|
||||||
|
|
||||||
|
Returns whether or not the operation was successful.
|
||||||
|
*/
|
||||||
|
typedef drwav_bool32 (* drwav_tell_proc)(void* pUserData, drwav_int64* pCursor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Callback for when drwav_init_ex() finds a chunk.
|
Callback for when drwav_init_ex() finds a chunk.
|
||||||
|
|
||||||
@ -514,6 +525,11 @@ typedef enum
|
|||||||
drwav_metadata_type_list_info_genre = 1 << 15,
|
drwav_metadata_type_list_info_genre = 1 << 15,
|
||||||
drwav_metadata_type_list_info_album = 1 << 16,
|
drwav_metadata_type_list_info_album = 1 << 16,
|
||||||
drwav_metadata_type_list_info_tracknumber = 1 << 17,
|
drwav_metadata_type_list_info_tracknumber = 1 << 17,
|
||||||
|
drwav_metadata_type_list_info_location = 1 << 18,
|
||||||
|
drwav_metadata_type_list_info_organization = 1 << 19,
|
||||||
|
drwav_metadata_type_list_info_keywords = 1 << 20,
|
||||||
|
drwav_metadata_type_list_info_medium = 1 << 21,
|
||||||
|
drwav_metadata_type_list_info_description = 1 << 22,
|
||||||
|
|
||||||
/* Other type constants for convenience. */
|
/* Other type constants for convenience. */
|
||||||
drwav_metadata_type_list_all_info_strings = drwav_metadata_type_list_info_software
|
drwav_metadata_type_list_all_info_strings = drwav_metadata_type_list_info_software
|
||||||
@ -524,7 +540,12 @@ typedef enum
|
|||||||
| drwav_metadata_type_list_info_date
|
| drwav_metadata_type_list_info_date
|
||||||
| drwav_metadata_type_list_info_genre
|
| drwav_metadata_type_list_info_genre
|
||||||
| drwav_metadata_type_list_info_album
|
| drwav_metadata_type_list_info_album
|
||||||
| drwav_metadata_type_list_info_tracknumber,
|
| drwav_metadata_type_list_info_tracknumber
|
||||||
|
| drwav_metadata_type_list_info_location
|
||||||
|
| drwav_metadata_type_list_info_organization
|
||||||
|
| drwav_metadata_type_list_info_keywords
|
||||||
|
| drwav_metadata_type_list_info_medium
|
||||||
|
| drwav_metadata_type_list_info_description,
|
||||||
|
|
||||||
drwav_metadata_type_list_all_adtl = drwav_metadata_type_list_label
|
drwav_metadata_type_list_all_adtl = drwav_metadata_type_list_label
|
||||||
| drwav_metadata_type_list_note
|
| drwav_metadata_type_list_note
|
||||||
@ -555,11 +576,11 @@ typedef struct
|
|||||||
/* See drwav_smpl_loop_type. */
|
/* See drwav_smpl_loop_type. */
|
||||||
drwav_uint32 type;
|
drwav_uint32 type;
|
||||||
|
|
||||||
/* The byte offset of the first sample to be played in the loop. */
|
/* The offset of the first sample to be played in the loop. */
|
||||||
drwav_uint32 firstSampleByteOffset;
|
drwav_uint32 firstSampleOffset;
|
||||||
|
|
||||||
/* The byte offset into the audio data of the last sample to be played in the loop. */
|
/* The offset into the audio data of the last sample to be played in the loop. */
|
||||||
drwav_uint32 lastSampleByteOffset;
|
drwav_uint32 lastSampleOffset;
|
||||||
|
|
||||||
/* A value to represent that playback should occur at a point between samples. This value ranges from 0 to UINT32_MAX. Where a value of 0 means no fraction, and a value of (UINT32_MAX / 2) would mean half a sample. */
|
/* A value to represent that playback should occur at a point between samples. This value ranges from 0 to UINT32_MAX. Where a value of 0 means no fraction, and a value of (UINT32_MAX / 2) would mean half a sample. */
|
||||||
drwav_uint32 sampleFraction;
|
drwav_uint32 sampleFraction;
|
||||||
@ -637,8 +658,8 @@ typedef struct
|
|||||||
/* Set to 0 for uncompressed formats. Else the last byte in compressed wave data where decompression can begin to find the value of the corresponding sample value. */
|
/* Set to 0 for uncompressed formats. Else the last byte in compressed wave data where decompression can begin to find the value of the corresponding sample value. */
|
||||||
drwav_uint32 blockStart;
|
drwav_uint32 blockStart;
|
||||||
|
|
||||||
/* For uncompressed formats this is the byte offset of the cue point into the audio data. For compressed formats this is relative to the block specified with blockStart. */
|
/* For uncompressed formats this is the offset of the cue point into the audio data. For compressed formats this is relative to the block specified with blockStart. */
|
||||||
drwav_uint32 sampleByteOffset;
|
drwav_uint32 sampleOffset;
|
||||||
} drwav_cue_point;
|
} drwav_cue_point;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -846,6 +867,9 @@ typedef struct
|
|||||||
/* A pointer to the function to call when the wav file needs to be seeked. */
|
/* A pointer to the function to call when the wav file needs to be seeked. */
|
||||||
drwav_seek_proc onSeek;
|
drwav_seek_proc onSeek;
|
||||||
|
|
||||||
|
/* A pointer to the function to call when the position of the stream needs to be retrieved. */
|
||||||
|
drwav_tell_proc onTell;
|
||||||
|
|
||||||
/* The user data to pass to callbacks. */
|
/* The user data to pass to callbacks. */
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
|
|
||||||
@ -968,9 +992,9 @@ after the function returns.
|
|||||||
|
|
||||||
See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
|
See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
|
||||||
*/
|
*/
|
||||||
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, drwav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initializes a pre-allocated drwav object for writing.
|
Initializes a pre-allocated drwav object for writing.
|
||||||
@ -1273,9 +1297,9 @@ Opens and reads an entire wav file in a single operation.
|
|||||||
|
|
||||||
The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
|
The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
|
||||||
*/
|
*/
|
||||||
DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
|
||||||
#ifndef DR_WAV_NO_STDIO
|
#ifndef DR_WAV_NO_STDIO
|
||||||
/*
|
/*
|
||||||
Opens and decodes an entire wav file in a single operation.
|
Opens and decodes an entire wav file in a single operation.
|
||||||
@ -1384,7 +1408,7 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
|
|||||||
#define DRWAV_MAX_SIMD_VECTOR_SIZE 32
|
#define DRWAV_MAX_SIMD_VECTOR_SIZE 32
|
||||||
|
|
||||||
/* Architecture Detection */
|
/* Architecture Detection */
|
||||||
#if defined(__x86_64__) || defined(_M_X64)
|
#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
||||||
#define DRWAV_X64
|
#define DRWAV_X64
|
||||||
#elif defined(__i386) || defined(_M_IX86)
|
#elif defined(__i386) || defined(_M_IX86)
|
||||||
#define DRWAV_X86
|
#define DRWAV_X86
|
||||||
@ -1962,12 +1986,12 @@ DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uin
|
|||||||
drwav_uint64 bytesRemainingToSeek = offset;
|
drwav_uint64 bytesRemainingToSeek = offset;
|
||||||
while (bytesRemainingToSeek > 0) {
|
while (bytesRemainingToSeek > 0) {
|
||||||
if (bytesRemainingToSeek > 0x7FFFFFFF) {
|
if (bytesRemainingToSeek > 0x7FFFFFFF) {
|
||||||
if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
|
if (!onSeek(pUserData, 0x7FFFFFFF, DRWAV_SEEK_CUR)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
bytesRemainingToSeek -= 0x7FFFFFFF;
|
bytesRemainingToSeek -= 0x7FFFFFFF;
|
||||||
} else {
|
} else {
|
||||||
if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
|
if (!onSeek(pUserData, (int)bytesRemainingToSeek, DRWAV_SEEK_CUR)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
bytesRemainingToSeek = 0;
|
bytesRemainingToSeek = 0;
|
||||||
@ -1980,21 +2004,21 @@ DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uin
|
|||||||
DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
|
DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
|
||||||
{
|
{
|
||||||
if (offset <= 0x7FFFFFFF) {
|
if (offset <= 0x7FFFFFFF) {
|
||||||
return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
|
return onSeek(pUserData, (int)offset, DRWAV_SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Larger than 32-bit seek. */
|
/* Larger than 32-bit seek. */
|
||||||
if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
|
if (!onSeek(pUserData, 0x7FFFFFFF, DRWAV_SEEK_SET)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
offset -= 0x7FFFFFFF;
|
offset -= 0x7FFFFFFF;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (offset <= 0x7FFFFFFF) {
|
if (offset <= 0x7FFFFFFF) {
|
||||||
return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
|
return onSeek(pUserData, (int)offset, DRWAV_SEEK_CUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
|
if (!onSeek(pUserData, 0x7FFFFFFF, DRWAV_SEEK_CUR)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
offset -= 0x7FFFFFFF;
|
offset -= 0x7FFFFFFF;
|
||||||
@ -2028,7 +2052,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserDat
|
|||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin == drwav_seek_origin_start) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
*pCursor = offset;
|
*pCursor = offset;
|
||||||
} else {
|
} else {
|
||||||
*pCursor += offset;
|
*pCursor += offset;
|
||||||
@ -2191,8 +2215,8 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
|||||||
if (bytesJustRead == sizeof(smplLoopData)) {
|
if (bytesJustRead == sizeof(smplLoopData)) {
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
|
pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
|
pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
|
pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleOffset = drwav_bytes_to_u32(smplLoopData + 8);
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
|
pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleOffset = drwav_bytes_to_u32(smplLoopData + 12);
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
|
pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
|
||||||
pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
|
pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
|
||||||
} else {
|
} else {
|
||||||
@ -2254,7 +2278,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parse
|
|||||||
pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
|
pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
|
||||||
pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
|
pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
|
||||||
pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
|
pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
|
||||||
pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
|
pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset = drwav_bytes_to_u32(cuePointData + 20);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2698,7 +2722,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
|
|||||||
drwav_uint8 buffer[4];
|
drwav_uint8 buffer[4];
|
||||||
size_t bytesJustRead;
|
size_t bytesJustRead;
|
||||||
|
|
||||||
if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
|
if (!pParser->onSeek(pParser->pReadSeekUserData, 28, DRWAV_SEEK_CUR)) {
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
bytesRead += 28;
|
bytesRead += 28;
|
||||||
@ -2811,7 +2835,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
|
|||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
allocSizeNeeded += drwav__strlen(buffer) + 1;
|
allocSizeNeeded += drwav__strlen(buffer) + 1;
|
||||||
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES; /* Coding history. */
|
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1; /* Coding history. */
|
||||||
|
|
||||||
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
|
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
|
||||||
|
|
||||||
@ -2916,6 +2940,16 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
|
|||||||
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
|
||||||
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
|
||||||
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
|
||||||
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_location, "IARL")) {
|
||||||
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_location);
|
||||||
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_organization, "ICMS")) {
|
||||||
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_organization);
|
||||||
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_keywords, "IKEY")) {
|
||||||
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_keywords);
|
||||||
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_medium, "IMED")) {
|
||||||
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_medium);
|
||||||
|
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_description, "ISBJ")) {
|
||||||
|
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_description);
|
||||||
} else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
|
} else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
|
||||||
subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
|
subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
|
||||||
}
|
}
|
||||||
@ -2926,14 +2960,14 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
|
|||||||
if (subchunkBytesRead < subchunkDataSize) {
|
if (subchunkBytesRead < subchunkDataSize) {
|
||||||
drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
|
drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
|
||||||
|
|
||||||
if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
|
if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, DRWAV_SEEK_CUR)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bytesRead += bytesToSeek;
|
bytesRead += bytesToSeek;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((subchunkDataSize % 2) == 1) {
|
if ((subchunkDataSize % 2) == 1) {
|
||||||
if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
|
if (!pParser->onSeek(pParser->pReadSeekUserData, 1, DRWAV_SEEK_CUR)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bytesRead += 1;
|
bytesRead += 1;
|
||||||
@ -2985,16 +3019,17 @@ DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pReadSeekTellUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
if (pWav == NULL || onRead == NULL || onSeek == NULL) {
|
if (pWav == NULL || onRead == NULL || onSeek == NULL) { /* <-- onTell is optional. */
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
|
DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
|
||||||
pWav->onRead = onRead;
|
pWav->onRead = onRead;
|
||||||
pWav->onSeek = onSeek;
|
pWav->onSeek = onSeek;
|
||||||
pWav->pUserData = pReadSeekUserData;
|
pWav->onTell = onTell;
|
||||||
|
pWav->pUserData = pReadSeekTellUserData;
|
||||||
pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
|
pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
|
||||||
|
|
||||||
if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
|
if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
|
||||||
@ -3311,7 +3346,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
fmt.channelMask = drwav_bytes_to_u32_ex(fmtext + 2, pWav->container);
|
fmt.channelMask = drwav_bytes_to_u32_ex(fmtext + 2, pWav->container);
|
||||||
drwav_bytes_to_guid(fmtext + 6, fmt.subFormat);
|
drwav_bytes_to_guid(fmtext + 6, fmt.subFormat);
|
||||||
} else {
|
} else {
|
||||||
if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, drwav_seek_origin_current) == DRWAV_FALSE) {
|
if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, DRWAV_SEEK_CUR) == DRWAV_FALSE) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3321,7 +3356,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
|
/* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current) == DRWAV_FALSE) {
|
if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), DRWAV_SEEK_CUR) == DRWAV_FALSE) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
cursor += (header.sizeInBytes - bytesReadSoFar);
|
cursor += (header.sizeInBytes - bytesReadSoFar);
|
||||||
@ -3471,6 +3506,9 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
I haven't been able to figure out how to get correct decoding for IMA ADPCM. Until this is figured out
|
I haven't been able to figure out how to get correct decoding for IMA ADPCM. Until this is figured out
|
||||||
we'll need to abort when we encounter such an encoding. Advice welcome!
|
we'll need to abort when we encounter such an encoding. Advice welcome!
|
||||||
*/
|
*/
|
||||||
|
(void)compressionFormat;
|
||||||
|
(void)sampleSizeInBits;
|
||||||
|
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
} else {
|
} else {
|
||||||
return DRWAV_FALSE; /* Unknown or unsupported compression format. Need to abort. */
|
return DRWAV_FALSE; /* Unknown or unsupported compression format. Need to abort. */
|
||||||
@ -3533,20 +3571,46 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to seek forward by the offset. */
|
/* The position of the audio data starts at an offset. */
|
||||||
offset = drwav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
|
offset = drwav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
|
||||||
|
pWav->dataChunkDataPos = cursor + offset;
|
||||||
|
|
||||||
|
/* The data chunk size needs to be reduced by the offset or else seeking will break. */
|
||||||
|
dataChunkSize = chunkSize;
|
||||||
|
if (dataChunkSize > offset) {
|
||||||
|
dataChunkSize -= offset;
|
||||||
|
} else {
|
||||||
|
dataChunkSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sequential) {
|
||||||
|
if (foundChunk_fmt) { /* <-- Name is misleading, but will be set to true if the COMM chunk has been parsed. */
|
||||||
|
/*
|
||||||
|
Getting here means we're opening in sequential mode and we've found the SSND (data) and COMM (fmt) chunks. We need
|
||||||
|
to get out of the loop here or else we'll end up going past the data chunk and will have no way of getting back to
|
||||||
|
it since we're not allowed to seek backwards.
|
||||||
|
|
||||||
|
One subtle detail here is that there is an offset with the SSND chunk. We need to make sure we seek past this offset
|
||||||
|
so we're left sitting on the first byte of actual audio data.
|
||||||
|
*/
|
||||||
if (drwav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == DRWAV_FALSE) {
|
if (drwav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == DRWAV_FALSE) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
cursor += offset;
|
cursor += offset;
|
||||||
|
|
||||||
pWav->dataChunkDataPos = cursor;
|
break;
|
||||||
dataChunkSize = chunkSize;
|
|
||||||
|
|
||||||
/* If we're running in sequential mode, or we're not reading metadata, we have enough now that we can get out of the loop. */
|
|
||||||
if (sequential || !isProcessingMetadata) {
|
|
||||||
break; /* No need to keep reading beyond the data chunk. */
|
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
Getting here means the COMM chunk was not found. In sequential mode, if we haven't yet found the COMM chunk
|
||||||
|
we'll need to abort because we can't be doing a backwards seek back to the SSND chunk in order to read the
|
||||||
|
data. For this reason, this configuration of AIFF files are not supported with sequential mode.
|
||||||
|
*/
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
|
||||||
|
chunkSize -= sizeof(offsetAndBlockSizeData); /* <-- This was read earlier. */
|
||||||
|
|
||||||
if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
|
if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3557,7 +3621,6 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */
|
/* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */
|
||||||
if (isProcessingMetadata) {
|
if (isProcessingMetadata) {
|
||||||
drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
|
drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
|
||||||
@ -3647,8 +3710,26 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
pWav->metadataCount = metadataParser.metadataCount;
|
pWav->metadataCount = metadataParser.metadataCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/* At this point we should be sitting on the first byte of the raw audio data. */
|
It's possible for the size reported in the data chunk to be greater than that of the file. We
|
||||||
|
need to do a validation check here to make sure we don't exceed the file size. To skip this
|
||||||
|
check, set the onTell callback to NULL.
|
||||||
|
*/
|
||||||
|
if (pWav->onTell != NULL && pWav->onSeek != NULL) {
|
||||||
|
if (pWav->onSeek(pWav->pUserData, 0, DRWAV_SEEK_END) == DRWAV_TRUE) {
|
||||||
|
drwav_int64 fileSize;
|
||||||
|
if (pWav->onTell(pWav->pUserData, &fileSize)) {
|
||||||
|
if (dataChunkSize + pWav->dataChunkDataPos > (drwav_uint64)fileSize) {
|
||||||
|
dataChunkSize = (drwav_uint64)fileSize - pWav->dataChunkDataPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
Failed to seek to the end of the file. It might not be supported by the backend so in
|
||||||
|
this case we cannot perform the validation check.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
I've seen a WAV file in the wild where a RIFF-ecapsulated file has the size of it's "RIFF" and
|
I've seen a WAV file in the wild where a RIFF-ecapsulated file has the size of it's "RIFF" and
|
||||||
@ -3670,6 +3751,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* At this point we want to be sitting on the first byte of the raw audio data. */
|
||||||
if (drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData) == DRWAV_FALSE) {
|
if (drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData) == DRWAV_FALSE) {
|
||||||
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
|
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
@ -3680,8 +3762,26 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
pWav->sampleRate = fmt.sampleRate;
|
pWav->sampleRate = fmt.sampleRate;
|
||||||
pWav->channels = fmt.channels;
|
pWav->channels = fmt.channels;
|
||||||
pWav->bitsPerSample = fmt.bitsPerSample;
|
pWav->bitsPerSample = fmt.bitsPerSample;
|
||||||
pWav->bytesRemaining = dataChunkSize;
|
|
||||||
pWav->translatedFormatTag = translatedFormatTag;
|
pWav->translatedFormatTag = translatedFormatTag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
I've had a report where files would start glitching after seeking. The reason for this is the data
|
||||||
|
chunk is not a clean multiple of the PCM frame size in bytes. Where this becomes a problem is when
|
||||||
|
seeking, because the number of bytes remaining in the data chunk is used to calculate the current
|
||||||
|
byte position. If this byte position is not aligned to the number of bytes in a PCM frame, it will
|
||||||
|
result in the seek not being cleanly positioned at the start of the PCM frame thereby resulting in
|
||||||
|
all decoded frames after that being corrupted.
|
||||||
|
|
||||||
|
To address this, we need to round the data chunk size down to the nearest multiple of the frame size.
|
||||||
|
*/
|
||||||
|
if (!drwav__is_compressed_format_tag(translatedFormatTag)) {
|
||||||
|
drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
|
||||||
|
if (bytesPerFrame > 0) {
|
||||||
|
dataChunkSize -= (dataChunkSize % bytesPerFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pWav->bytesRemaining = dataChunkSize;
|
||||||
pWav->dataChunkDataSize = dataChunkSize;
|
pWav->dataChunkDataSize = dataChunkSize;
|
||||||
|
|
||||||
if (sampleCountFromFactChunk != 0) {
|
if (sampleCountFromFactChunk != 0) {
|
||||||
@ -3764,23 +3864,23 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
|||||||
return DRWAV_TRUE;
|
return DRWAV_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
|
return drwav_init_ex(pWav, onRead, onSeek, onTell, NULL, pUserData, NULL, 0, pAllocationCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, drwav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
|
if (!drwav_preinit(pWav, onRead, onSeek, onTell, pReadSeekTellUserData, pAllocationCallbacks)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
|
return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
|
if (!drwav_preinit(pWav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3995,8 +4095,8 @@ DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata*
|
|||||||
for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
|
for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleOffset);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleOffset);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
|
||||||
}
|
}
|
||||||
@ -4036,7 +4136,7 @@ DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata*
|
|||||||
bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
|
bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
|
||||||
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
|
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -4151,6 +4251,11 @@ DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata*
|
|||||||
case drwav_metadata_type_list_info_genre: pID = "IGNR"; break;
|
case drwav_metadata_type_list_info_genre: pID = "IGNR"; break;
|
||||||
case drwav_metadata_type_list_info_album: pID = "IPRD"; break;
|
case drwav_metadata_type_list_info_album: pID = "IPRD"; break;
|
||||||
case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
|
case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
|
||||||
|
case drwav_metadata_type_list_info_location: pID = "IARL"; break;
|
||||||
|
case drwav_metadata_type_list_info_organization: pID = "ICMS"; break;
|
||||||
|
case drwav_metadata_type_list_info_keywords: pID = "IKEY"; break;
|
||||||
|
case drwav_metadata_type_list_info_medium: pID = "IMED"; break;
|
||||||
|
case drwav_metadata_type_list_info_description: pID = "ISBJ"; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4434,7 +4539,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_d
|
|||||||
|
|
||||||
/* "RIFF" chunk. */
|
/* "RIFF" chunk. */
|
||||||
if (pFormat->container == drwav_container_riff) {
|
if (pFormat->container == drwav_container_riff) {
|
||||||
drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize; /* +28 = "WAVE" + [sizeof "fmt " chunk] */
|
drwav_uint32 chunkSizeRIFF = 36 + (drwav_uint32)initialDataChunkSize; /* +36 = "WAVE" + [sizeof "fmt " chunk] + [data chunk header] */
|
||||||
runningPos += drwav__write(pWav, "RIFF", 4);
|
runningPos += drwav__write(pWav, "RIFF", 4);
|
||||||
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
|
||||||
runningPos += drwav__write(pWav, "WAVE", 4);
|
runningPos += drwav__write(pWav, "WAVE", 4);
|
||||||
@ -4704,7 +4809,7 @@ DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
|
|||||||
#ifdef ENOSYS
|
#ifdef ENOSYS
|
||||||
case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
|
case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENOTEMPTY
|
#if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST /* In AIX, ENOTEMPTY and EEXIST use the same value. */
|
||||||
case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
|
case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ELOOP
|
#ifdef ELOOP
|
||||||
@ -5161,7 +5266,38 @@ DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, s
|
|||||||
|
|
||||||
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
|
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
|
||||||
{
|
{
|
||||||
return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
int whence = SEEK_SET;
|
||||||
|
if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
whence = SEEK_CUR;
|
||||||
|
} else if (origin == DRWAV_SEEK_END) {
|
||||||
|
whence = SEEK_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fseek((FILE*)pUserData, offset, whence) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pCursor)
|
||||||
|
{
|
||||||
|
FILE* pFileStdio = (FILE*)pUserData;
|
||||||
|
drwav_int64 result;
|
||||||
|
|
||||||
|
/* These were all validated at a higher level. */
|
||||||
|
DRWAV_ASSERT(pFileStdio != NULL);
|
||||||
|
DRWAV_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
|
result = _ftelli64(pFileStdio);
|
||||||
|
#else
|
||||||
|
result = ftell(pFileStdio);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
result = ftell(pFileStdio);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*pCursor = result;
|
||||||
|
|
||||||
|
return DRWAV_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
@ -5174,7 +5310,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFi
|
|||||||
{
|
{
|
||||||
drwav_bool32 result;
|
drwav_bool32 result;
|
||||||
|
|
||||||
result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, drwav__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||||
if (result != DRWAV_TRUE) {
|
if (result != DRWAV_TRUE) {
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return result;
|
return result;
|
||||||
@ -5352,29 +5488,34 @@ DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, si
|
|||||||
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
|
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
|
||||||
{
|
{
|
||||||
drwav* pWav = (drwav*)pUserData;
|
drwav* pWav = (drwav*)pUserData;
|
||||||
|
drwav_int64 newCursor;
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
if (origin == drwav_seek_origin_current) {
|
newCursor = pWav->memoryStream.currentReadPos;
|
||||||
if (offset > 0) {
|
|
||||||
if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
return DRWAV_FALSE; /* Trying to seek too far forward. */
|
newCursor = 0;
|
||||||
}
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
newCursor = (drwav_int64)pWav->memoryStream.currentReadPos;
|
||||||
|
} else if (origin == DRWAV_SEEK_END) {
|
||||||
|
newCursor = (drwav_int64)pWav->memoryStream.dataSize;
|
||||||
} else {
|
} else {
|
||||||
if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
|
DRWAV_ASSERT(!"Invalid seek origin");
|
||||||
return DRWAV_FALSE; /* Trying to seek too far backwards. */
|
return DRWAV_FALSE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This will never underflow thanks to the clamps above. */
|
newCursor += offset;
|
||||||
pWav->memoryStream.currentReadPos += offset;
|
|
||||||
} else {
|
if (newCursor < 0) {
|
||||||
if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
|
return DRWAV_FALSE; /* Trying to seek prior to the start of the buffer. */
|
||||||
pWav->memoryStream.currentReadPos = offset;
|
|
||||||
} else {
|
|
||||||
return DRWAV_FALSE; /* Trying to seek too far forward. */
|
|
||||||
}
|
}
|
||||||
|
if ((size_t)newCursor > pWav->memoryStream.dataSize) {
|
||||||
|
return DRWAV_FALSE; /* Trying to seek beyond the end of the buffer. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pWav->memoryStream.currentReadPos = (size_t)newCursor;
|
||||||
|
|
||||||
return DRWAV_TRUE;
|
return DRWAV_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5421,29 +5562,45 @@ DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn
|
|||||||
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
|
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
|
||||||
{
|
{
|
||||||
drwav* pWav = (drwav*)pUserData;
|
drwav* pWav = (drwav*)pUserData;
|
||||||
|
drwav_int64 newCursor;
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
if (origin == drwav_seek_origin_current) {
|
newCursor = pWav->memoryStreamWrite.currentWritePos;
|
||||||
if (offset > 0) {
|
|
||||||
if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos); /* Trying to seek too far forward. */
|
newCursor = 0;
|
||||||
}
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
newCursor = (drwav_int64)pWav->memoryStreamWrite.currentWritePos;
|
||||||
|
} else if (origin == DRWAV_SEEK_END) {
|
||||||
|
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
||||||
} else {
|
} else {
|
||||||
if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
|
DRWAV_ASSERT(!"Invalid seek origin");
|
||||||
offset = -(int)pWav->memoryStreamWrite.currentWritePos; /* Trying to seek too far backwards. */
|
return DRWAV_INVALID_ARGS;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This will never underflow thanks to the clamps above. */
|
newCursor += offset;
|
||||||
pWav->memoryStreamWrite.currentWritePos += offset;
|
|
||||||
} else {
|
if (newCursor < 0) {
|
||||||
if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
|
return DRWAV_FALSE; /* Trying to seek prior to the start of the buffer. */
|
||||||
pWav->memoryStreamWrite.currentWritePos = offset;
|
|
||||||
} else {
|
|
||||||
pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize; /* Trying to seek too far forward. */
|
|
||||||
}
|
}
|
||||||
|
if ((size_t)newCursor > pWav->memoryStreamWrite.dataSize) {
|
||||||
|
return DRWAV_FALSE; /* Trying to seek beyond the end of the buffer. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pWav->memoryStreamWrite.currentWritePos = (size_t)newCursor;
|
||||||
|
|
||||||
|
return DRWAV_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRWAV_PRIVATE drwav_bool32 drwav__on_tell_memory(void* pUserData, drwav_int64* pCursor)
|
||||||
|
{
|
||||||
|
drwav* pWav = (drwav*)pUserData;
|
||||||
|
|
||||||
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
DRWAV_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
|
*pCursor = (drwav_int64)pWav->memoryStream.currentReadPos;
|
||||||
return DRWAV_TRUE;
|
return DRWAV_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5458,7 +5615,7 @@ DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_
|
|||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
|
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, drwav__on_tell_memory, pWav, pAllocationCallbacks)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5475,7 +5632,7 @@ DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void*
|
|||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
|
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, drwav__on_tell_memory, pWav, pAllocationCallbacks)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5565,25 +5722,25 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
|||||||
if (pWav->onSeek && !pWav->isSequentialWrite) {
|
if (pWav->onSeek && !pWav->isSequentialWrite) {
|
||||||
if (pWav->container == drwav_container_riff) {
|
if (pWav->container == drwav_container_riff) {
|
||||||
/* The "RIFF" chunk size. */
|
/* The "RIFF" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, 4, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
|
drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
|
||||||
drwav__write_u32ne_to_le(pWav, riffChunkSize);
|
drwav__write_u32ne_to_le(pWav, riffChunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The "data" chunk size. */
|
/* The "data" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
|
drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
|
||||||
drwav__write_u32ne_to_le(pWav, dataChunkSize);
|
drwav__write_u32ne_to_le(pWav, dataChunkSize);
|
||||||
}
|
}
|
||||||
} else if (pWav->container == drwav_container_w64) {
|
} else if (pWav->container == drwav_container_w64) {
|
||||||
/* The "RIFF" chunk size. */
|
/* The "RIFF" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, 16, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
|
||||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The "data" chunk size. */
|
/* The "data" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
|
drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
|
||||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||||
}
|
}
|
||||||
@ -5592,13 +5749,13 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
|
|||||||
int ds64BodyPos = 12 + 8;
|
int ds64BodyPos = 12 + 8;
|
||||||
|
|
||||||
/* The "RIFF" chunk size. */
|
/* The "RIFF" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
|
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
|
||||||
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
drwav__write_u64ne_to_le(pWav, riffChunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The "data" chunk size. */
|
/* The "data" chunk size. */
|
||||||
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
|
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, DRWAV_SEEK_SET)) {
|
||||||
drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
|
drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
|
||||||
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
drwav__write_u64ne_to_le(pWav, dataChunkSize);
|
||||||
}
|
}
|
||||||
@ -5663,7 +5820,7 @@ DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOu
|
|||||||
bytesToSeek = 0x7FFFFFFF;
|
bytesToSeek = 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
|
if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, DRWAV_SEEK_CUR) == DRWAV_FALSE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5810,7 +5967,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(drwav* pWav)
|
|||||||
return DRWAV_FALSE; /* No seeking in write mode. */
|
return DRWAV_FALSE; /* No seeking in write mode. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
|
if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, DRWAV_SEEK_SET)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5928,7 +6085,7 @@ DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetF
|
|||||||
|
|
||||||
while (offset > 0) {
|
while (offset > 0) {
|
||||||
int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
|
int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
|
||||||
if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
|
if (!pWav->onSeek(pWav->pUserData, offset32, DRWAV_SEEK_CUR)) {
|
||||||
return DRWAV_FALSE;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6101,6 +6258,13 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||||||
{
|
{
|
||||||
drwav_uint64 totalFramesRead = 0;
|
drwav_uint64 totalFramesRead = 0;
|
||||||
|
|
||||||
|
static drwav_int32 adaptationTable[] = {
|
||||||
|
230, 230, 230, 230, 307, 409, 512, 614,
|
||||||
|
768, 614, 512, 409, 307, 230, 230, 230
|
||||||
|
};
|
||||||
|
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||||
|
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
DRWAV_ASSERT(framesToRead > 0);
|
DRWAV_ASSERT(framesToRead > 0);
|
||||||
|
|
||||||
@ -6126,6 +6290,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||||||
pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
|
pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
|
||||||
pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
||||||
|
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table)) {
|
||||||
|
return totalFramesRead; /* Invalid file. */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Stereo. */
|
/* Stereo. */
|
||||||
drwav_uint8 header[14];
|
drwav_uint8 header[14];
|
||||||
@ -6148,6 +6317,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||||||
pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
|
pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
||||||
|
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead; /* Invalid file. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6181,13 +6355,6 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||||||
if (pWav->msadpcm.bytesRemainingInBlock == 0) {
|
if (pWav->msadpcm.bytesRemainingInBlock == 0) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
static drwav_int32 adaptationTable[] = {
|
|
||||||
230, 230, 230, 230, 307, 409, 512, 614,
|
|
||||||
768, 614, 512, 409, 307, 230, 230, 230
|
|
||||||
};
|
|
||||||
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
|
||||||
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
|
||||||
|
|
||||||
drwav_uint8 nibbles;
|
drwav_uint8 nibbles;
|
||||||
drwav_int32 nibble0;
|
drwav_int32 nibble0;
|
||||||
drwav_int32 nibble1;
|
drwav_int32 nibble1;
|
||||||
@ -6320,7 +6487,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
|||||||
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
|
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
|
||||||
|
|
||||||
if (header[2] >= drwav_countof(stepTable)) {
|
if (header[2] >= drwav_countof(stepTable)) {
|
||||||
pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
|
pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, DRWAV_SEEK_CUR);
|
||||||
pWav->ima.bytesRemainingInBlock = 0;
|
pWav->ima.bytesRemainingInBlock = 0;
|
||||||
return totalFramesRead; /* Invalid data. */
|
return totalFramesRead; /* Invalid data. */
|
||||||
}
|
}
|
||||||
@ -6338,7 +6505,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
|||||||
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
|
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
|
||||||
|
|
||||||
if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
|
if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
|
||||||
pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
|
pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, DRWAV_SEEK_CUR);
|
||||||
pWav->ima.bytesRemainingInBlock = 0;
|
pWav->ima.bytesRemainingInBlock = 0;
|
||||||
return totalFramesRead; /* Invalid data. */
|
return totalFramesRead; /* Invalid data. */
|
||||||
}
|
}
|
||||||
@ -8006,7 +8173,7 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drwav wav;
|
drwav wav;
|
||||||
|
|
||||||
@ -8020,14 +8187,14 @@ DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead
|
|||||||
*totalFrameCountOut = 0;
|
*totalFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
|
if (!drwav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
|
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drwav wav;
|
drwav wav;
|
||||||
|
|
||||||
@ -8041,14 +8208,14 @@ DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwa
|
|||||||
*totalFrameCountOut = 0;
|
*totalFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
|
if (!drwav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
|
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
drwav wav;
|
drwav wav;
|
||||||
|
|
||||||
@ -8062,7 +8229,7 @@ DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead
|
|||||||
*totalFrameCountOut = 0;
|
*totalFrameCountOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
|
if (!drwav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8350,6 +8517,27 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
|
|||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
|
v0.14.0 - TBD
|
||||||
|
- API CHANGE: Seek origin enums have been renamed to the following:
|
||||||
|
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
||||||
|
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
||||||
|
- DRWAV_SEEK_END (new)
|
||||||
|
- API CHANGE: A new seek origin has been added to allow seeking from the end of the file. If you implement your own `onSeek` callback, you must now handle `DRWAV_SEEK_END`. If you only use `*_init_file()` or `*_init_memory()`, you need not change anything.
|
||||||
|
- API CHANGE: An `onTell` callback has been added to the following functions:
|
||||||
|
- drwav_init()
|
||||||
|
- drwav_init_ex()
|
||||||
|
- drwav_init_with_metadata()
|
||||||
|
- drwav_open_and_read_pcm_frames_s16()
|
||||||
|
- drwav_open_and_read_pcm_frames_f32()
|
||||||
|
- drwav_open_and_read_pcm_frames_s32()
|
||||||
|
- API CHANGE: The `firstSampleByteOffset`, `lastSampleByteOffset` and `sampleByteOffset` members of `drwav_cue_point` have been renamed to `firstSampleOffset`, `lastSampleOffset` and `sampleOffset`, respectively.
|
||||||
|
- Fix a static analysis warning.
|
||||||
|
- Fix compilation for AIX OS.
|
||||||
|
|
||||||
|
v0.13.17 - 2024-12-17
|
||||||
|
- Fix a possible crash when reading from MS-ADPCM encoded files.
|
||||||
|
- Improve detection of ARM64EC
|
||||||
|
|
||||||
v0.13.16 - 2024-02-27
|
v0.13.16 - 2024-02-27
|
||||||
- Fix a Wdouble-promotion warning.
|
- Fix a Wdouble-promotion warning.
|
||||||
|
|
||||||
|
2107
src/external/glfw/src/mappings.h
vendored
2107
src/external/glfw/src/mappings.h
vendored
File diff suppressed because it is too large
Load Diff
1649
src/external/miniaudio.h
vendored
1649
src/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load Diff
2
src/external/rprand.h
vendored
2
src/external/rprand.h
vendored
@ -90,7 +90,7 @@
|
|||||||
#define RPRAND_FREE(ptr) free(ptr)
|
#define RPRAND_FREE(ptr) free(ptr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Simple log system to avoid RPNG_LOG() calls if required
|
// Simple log system to avoid log calls if required
|
||||||
// NOTE: Avoiding those calls, also avoids const strings memory usage
|
// NOTE: Avoiding those calls, also avoids const strings memory usage
|
||||||
#define RPRAND_SHOW_LOG_INFO
|
#define RPRAND_SHOW_LOG_INFO
|
||||||
#if defined(RPNG_SHOW_LOG_INFO)
|
#if defined(RPNG_SHOW_LOG_INFO)
|
||||||
|
@ -70,6 +70,16 @@ typedef struct {
|
|||||||
EGLConfig config; // Graphic config
|
EGLConfig config; // Graphic config
|
||||||
} PlatformData;
|
} PlatformData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Store data for both Hover and Touch events
|
||||||
|
// Used to ignore Hover events which are interpreted as Touch events
|
||||||
|
int32_t pointCount; // Number of touch points active
|
||||||
|
int32_t pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
||||||
|
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||||
|
|
||||||
|
int32_t hoverPoints[MAX_TOUCH_POINTS]; // Hover Points
|
||||||
|
} TouchRaw;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -246,6 +256,8 @@ static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
|
|||||||
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
|
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static TouchRaw touchRaw = { 0 };
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Declaration
|
// Module Internal Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -801,6 +813,8 @@ int InitPlatform(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) touchRaw.hoverPoints[i] = -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,25 +1283,85 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register touch points count
|
// Register touch points count
|
||||||
CORE.Input.Touch.pointCount = AMotionEvent_getPointerCount(event);
|
touchRaw.pointCount = AMotionEvent_getPointerCount(event);
|
||||||
|
|
||||||
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
{
|
{
|
||||||
// Register touch points id
|
// Register touch points id
|
||||||
CORE.Input.Touch.pointId[i] = AMotionEvent_getPointerId(event, i);
|
touchRaw.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||||
|
|
||||||
// Register touch points position
|
// Register touch points position
|
||||||
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
touchRaw.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
||||||
|
|
||||||
// Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height
|
// Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height
|
||||||
float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;
|
float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;
|
||||||
float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;
|
float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;
|
||||||
CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
|
touchRaw.position[i].x = touchRaw.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
|
||||||
CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
|
touchRaw.position[i].y = touchRaw.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t action = AMotionEvent_getAction(event);
|
int32_t action = AMotionEvent_getAction(event);
|
||||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||||
|
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_HOVER_ENTER)
|
||||||
|
{
|
||||||
|
// The new pointer is hover
|
||||||
|
// So add it to hoverPoints
|
||||||
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||||
|
{
|
||||||
|
if (touchRaw.hoverPoints[i] == -1)
|
||||||
|
{
|
||||||
|
touchRaw.hoverPoints[i] = touchRaw.pointId[pointerIndex];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags == AMOTION_EVENT_ACTION_POINTER_UP) || (flags == AMOTION_EVENT_ACTION_UP) || (flags == AMOTION_EVENT_ACTION_HOVER_EXIT))
|
||||||
|
{
|
||||||
|
// One of the touchpoints is released, remove it from touch point arrays
|
||||||
|
if (flags == AMOTION_EVENT_ACTION_HOVER_EXIT)
|
||||||
|
{
|
||||||
|
// If the touchPoint is hover, remove it from hoverPoints
|
||||||
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||||
|
{
|
||||||
|
if (touchRaw.hoverPoints[i] == touchRaw.pointId[pointerIndex])
|
||||||
|
{
|
||||||
|
touchRaw.hoverPoints[i] = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = pointerIndex; (i < touchRaw.pointCount - 1) && (i < MAX_TOUCH_POINTS - 1); i++)
|
||||||
|
{
|
||||||
|
touchRaw.pointId[i] = touchRaw.pointId[i+1];
|
||||||
|
touchRaw.position[i] = touchRaw.position[i+1];
|
||||||
|
}
|
||||||
|
touchRaw.pointCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pointCount = 0;
|
||||||
|
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||||
|
{
|
||||||
|
// If the touchPoint is hover, Ignore it
|
||||||
|
bool hover = false;
|
||||||
|
for (int j = 0; j < MAX_TOUCH_POINTS; j++)
|
||||||
|
{
|
||||||
|
// Check if the touchPoint is in hoverPointers
|
||||||
|
if (touchRaw.hoverPoints[j] == touchRaw.pointId[i])
|
||||||
|
{
|
||||||
|
hover = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hover) continue;
|
||||||
|
|
||||||
|
CORE.Input.Touch.pointId[pointCount] = touchRaw.pointId[i];
|
||||||
|
CORE.Input.Touch.position[pointCount] = touchRaw.position[i];
|
||||||
|
pointCount++;
|
||||||
|
}
|
||||||
|
CORE.Input.Touch.pointCount = pointCount;
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
GestureEvent gestureEvent = { 0 };
|
GestureEvent gestureEvent = { 0 };
|
||||||
@ -1312,20 +1386,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
|
||||||
|
|
||||||
if (flags == AMOTION_EVENT_ACTION_POINTER_UP || flags == AMOTION_EVENT_ACTION_UP)
|
|
||||||
{
|
|
||||||
// One of the touchpoints is released, remove it from touch point arrays
|
|
||||||
for (int i = pointerIndex; (i < CORE.Input.Touch.pointCount - 1) && (i < MAX_TOUCH_POINTS); i++)
|
|
||||||
{
|
|
||||||
CORE.Input.Touch.pointId[i] = CORE.Input.Touch.pointId[i+1];
|
|
||||||
CORE.Input.Touch.position[i] = CORE.Input.Touch.position[i+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
CORE.Input.Touch.pointCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When all touchpoints are tapped and released really quickly, this event is generated
|
// When all touchpoints are tapped and released really quickly, this event is generated
|
||||||
if (flags == AMOTION_EVENT_ACTION_CANCEL) CORE.Input.Touch.pointCount = 0;
|
if (flags == AMOTION_EVENT_ACTION_CANCEL) CORE.Input.Touch.pointCount = 0;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* rcore_desktop - Functions to manage window, graphics device and inputs
|
* rcore_desktop_glfw - Functions to manage window, graphics device and inputs
|
||||||
*
|
*
|
||||||
* PLATFORM: DESKTOP: GLFW
|
* PLATFORM: DESKTOP: GLFW
|
||||||
* - Windows (Win32, Win64)
|
* - Windows (Win32, Win64)
|
||||||
@ -576,7 +576,7 @@ void SetWindowIcons(Image *images, int count)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int valid = 0;
|
int valid = 0;
|
||||||
GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));
|
GLFWimage *icons = (GLFWimage *)RL_CALLOC(count, sizeof(GLFWimage));
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@ -1238,7 +1238,7 @@ void PollInputEvents(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current axis state
|
// Get current state of axes
|
||||||
const float *axes = state.axes;
|
const float *axes = state.axes;
|
||||||
|
|
||||||
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
|
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
|
||||||
@ -1246,7 +1246,7 @@ void PollInputEvents(void)
|
|||||||
CORE.Input.Gamepad.axisState[i][k] = axes[k];
|
CORE.Input.Gamepad.axisState[i][k] = axes[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
|
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather as axes)
|
||||||
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f)
|
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f)
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1;
|
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1;
|
||||||
@ -1327,6 +1327,7 @@ int InitPlatform(void)
|
|||||||
.reallocate = ReallocateWrapper,
|
.reallocate = ReallocateWrapper,
|
||||||
.user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data
|
.user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data
|
||||||
};
|
};
|
||||||
|
|
||||||
glfwInitAllocator(&allocator);
|
glfwInitAllocator(&allocator);
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -1696,6 +1697,8 @@ int InitPlatform(void)
|
|||||||
// Retrieve gamepad names
|
// Retrieve gamepad names
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
{
|
{
|
||||||
|
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||||
|
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
|
||||||
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -1752,6 +1755,10 @@ static void ErrorCallback(int error, const char *description)
|
|||||||
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
|
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||||
{
|
{
|
||||||
|
// WARNING: On window minimization, callback is called,
|
||||||
|
// but we don't want to change internal screen values, it breaks things
|
||||||
|
if ((width == 0) || (height == 0)) return;
|
||||||
|
|
||||||
// Reset viewport and projection matrix for new size
|
// Reset viewport and projection matrix for new size
|
||||||
SetupViewport(width, height);
|
SetupViewport(width, height);
|
||||||
|
|
||||||
@ -1969,6 +1976,9 @@ static void JoystickCallback(int jid, int event)
|
|||||||
{
|
{
|
||||||
if (event == GLFW_CONNECTED)
|
if (event == GLFW_CONNECTED)
|
||||||
{
|
{
|
||||||
|
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||||
|
// we can get a not-NULL terminated string, so, we clean destination and only copy up to -1
|
||||||
|
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||||
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||||
}
|
}
|
||||||
else if (event == GLFW_DISCONNECTED)
|
else if (event == GLFW_DISCONNECTED)
|
||||||
|
@ -175,7 +175,9 @@ static const unsigned short keyMappingRGFW[] = {
|
|||||||
[RGFW_superL] = KEY_LEFT_SUPER,
|
[RGFW_superL] = KEY_LEFT_SUPER,
|
||||||
#ifndef RGFW_MACOS
|
#ifndef RGFW_MACOS
|
||||||
[RGFW_shiftR] = KEY_RIGHT_SHIFT,
|
[RGFW_shiftR] = KEY_RIGHT_SHIFT,
|
||||||
|
[RGFW_controlR] = KEY_RIGHT_CONTROL,
|
||||||
[RGFW_altR] = KEY_RIGHT_ALT,
|
[RGFW_altR] = KEY_RIGHT_ALT,
|
||||||
|
[RGFW_superR] = KEY_RIGHT_SUPER,
|
||||||
#endif
|
#endif
|
||||||
[RGFW_space] = KEY_SPACE,
|
[RGFW_space] = KEY_SPACE,
|
||||||
|
|
||||||
@ -583,7 +585,7 @@ void SetWindowPosition(int x, int y)
|
|||||||
// Set monitor for the current window
|
// Set monitor for the current window
|
||||||
void SetWindowMonitor(int monitor)
|
void SetWindowMonitor(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]);
|
RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors(NULL)[monitor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||||
@ -640,7 +642,7 @@ int GetMonitorCount(void)
|
|||||||
#define MAX_MONITORS_SUPPORTED 6
|
#define MAX_MONITORS_SUPPORTED 6
|
||||||
|
|
||||||
int count = MAX_MONITORS_SUPPORTED;
|
int count = MAX_MONITORS_SUPPORTED;
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
@ -657,7 +659,7 @@ int GetMonitorCount(void)
|
|||||||
// Get current monitor where window is placed
|
// Get current monitor where window is placed
|
||||||
int GetCurrentMonitor(void)
|
int GetCurrentMonitor(void)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
RGFW_monitor mon = { 0 };
|
RGFW_monitor mon = { 0 };
|
||||||
|
|
||||||
if (platform.window) mon = RGFW_window_getMonitor(platform.window);
|
if (platform.window) mon = RGFW_window_getMonitor(platform.window);
|
||||||
@ -674,7 +676,7 @@ int GetCurrentMonitor(void)
|
|||||||
// Get selected monitor position
|
// Get selected monitor position
|
||||||
Vector2 GetMonitorPosition(int monitor)
|
Vector2 GetMonitorPosition(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y };
|
return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y };
|
||||||
}
|
}
|
||||||
@ -682,7 +684,7 @@ Vector2 GetMonitorPosition(int monitor)
|
|||||||
// Get selected monitor width (currently used by monitor)
|
// Get selected monitor width (currently used by monitor)
|
||||||
int GetMonitorWidth(int monitor)
|
int GetMonitorWidth(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return mons[monitor].mode.area.w;
|
return mons[monitor].mode.area.w;
|
||||||
}
|
}
|
||||||
@ -690,7 +692,7 @@ int GetMonitorWidth(int monitor)
|
|||||||
// Get selected monitor height (currently used by monitor)
|
// Get selected monitor height (currently used by monitor)
|
||||||
int GetMonitorHeight(int monitor)
|
int GetMonitorHeight(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return mons[monitor].mode.area.h;
|
return mons[monitor].mode.area.h;
|
||||||
}
|
}
|
||||||
@ -698,7 +700,7 @@ int GetMonitorHeight(int monitor)
|
|||||||
// Get selected monitor physical width in millimetres
|
// Get selected monitor physical width in millimetres
|
||||||
int GetMonitorPhysicalWidth(int monitor)
|
int GetMonitorPhysicalWidth(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return mons[monitor].physW;
|
return mons[monitor].physW;
|
||||||
}
|
}
|
||||||
@ -706,7 +708,7 @@ int GetMonitorPhysicalWidth(int monitor)
|
|||||||
// Get selected monitor physical height in millimetres
|
// Get selected monitor physical height in millimetres
|
||||||
int GetMonitorPhysicalHeight(int monitor)
|
int GetMonitorPhysicalHeight(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return (int)mons[monitor].physH;
|
return (int)mons[monitor].physH;
|
||||||
}
|
}
|
||||||
@ -714,7 +716,7 @@ int GetMonitorPhysicalHeight(int monitor)
|
|||||||
// Get selected monitor refresh rate
|
// Get selected monitor refresh rate
|
||||||
int GetMonitorRefreshRate(int monitor)
|
int GetMonitorRefreshRate(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return (int)mons[monitor].mode.refreshRate;
|
return (int)mons[monitor].mode.refreshRate;
|
||||||
}
|
}
|
||||||
@ -722,7 +724,7 @@ int GetMonitorRefreshRate(int monitor)
|
|||||||
// Get the human-readable, UTF-8 encoded name of the selected monitor
|
// Get the human-readable, UTF-8 encoded name of the selected monitor
|
||||||
const char *GetMonitorName(int monitor)
|
const char *GetMonitorName(int monitor)
|
||||||
{
|
{
|
||||||
RGFW_monitor *mons = RGFW_getMonitors();
|
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||||
|
|
||||||
return mons[monitor].name;
|
return mons[monitor].name;
|
||||||
}
|
}
|
||||||
@ -987,7 +989,7 @@ void PollInputEvents(void)
|
|||||||
|
|
||||||
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
|
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
|
||||||
{
|
{
|
||||||
RGFW_window_eventWait(platform.window, 0); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
RGFW_window_eventWait(platform.window, -1); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
||||||
CORE.Time.previous = GetTime();
|
CORE.Time.previous = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1319,6 +1321,13 @@ int InitPlatform(void)
|
|||||||
platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
|
platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
|
||||||
platform.mon.mode.area.w = 0;
|
platform.mon.mode.area.w = 0;
|
||||||
|
|
||||||
|
if (platform.window != NULL)
|
||||||
|
{
|
||||||
|
// NOTE: RGFW's exit key is distinct from raylib's exit key (which can
|
||||||
|
// be set with SetExitKey()) and defaults to Escape
|
||||||
|
platform.window->exitKey = RGFW_keyNULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PLATFORM_WEB_RGFW
|
#ifndef PLATFORM_WEB_RGFW
|
||||||
RGFW_area screenSize = RGFW_getScreenSize();
|
RGFW_area screenSize = RGFW_getScreenSize();
|
||||||
CORE.Window.display.width = screenSize.w;
|
CORE.Window.display.width = screenSize.w;
|
||||||
|
@ -424,6 +424,8 @@ void ClosePlatform(void); // Close platform
|
|||||||
|
|
||||||
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode); // Help convert SDL scancodes to raylib key
|
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode); // Help convert SDL scancodes to raylib key
|
||||||
|
|
||||||
|
static int GetCodepointNextSDL(const char *text, int *codepointSize); // Get next codepoint in a byte sequence and bytes processed
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -1601,13 +1603,18 @@ void PollInputEvents(void)
|
|||||||
{
|
{
|
||||||
// NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
|
// NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
|
||||||
|
|
||||||
int codepointSize = 0;
|
|
||||||
|
|
||||||
// Check if there is space available in the queue
|
// Check if there is space available in the queue
|
||||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
||||||
{
|
{
|
||||||
// Add character (codepoint) to the queue
|
// Add character (codepoint) to the queue
|
||||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = GetCodepointNext(event.text.text, &codepointSize);
|
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||||
|
unsigned int textLen = strlen(event.text.text);
|
||||||
|
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, textLen);
|
||||||
|
#else
|
||||||
|
int codepointSize = 0;
|
||||||
|
int codepoint = GetCodepointNextSDL(event.text.text, &codepointSize);
|
||||||
|
#endif
|
||||||
|
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;
|
||||||
CORE.Input.Keyboard.charPressedQueueCount++;
|
CORE.Input.Keyboard.charPressedQueueCount++;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -1697,8 +1704,8 @@ void PollInputEvents(void)
|
|||||||
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
|
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
|
||||||
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
|
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
|
||||||
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
||||||
|
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||||
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||||
CORE.Input.Gamepad.name[jid][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1825,7 +1832,7 @@ void PollInputEvents(void)
|
|||||||
{
|
{
|
||||||
if (platform.gamepadId[i] == event.jaxis.which)
|
if (platform.gamepadId[i] == event.jaxis.which)
|
||||||
{
|
{
|
||||||
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
|
// SDL axis value range is -32768 to 32767, we normalize it to raylib's -1.0 to 1.0f range
|
||||||
float value = event.jaxis.value/(float)32767;
|
float value = event.jaxis.value/(float)32767;
|
||||||
CORE.Input.Gamepad.axisState[i][axis] = value;
|
CORE.Input.Gamepad.axisState[i][axis] = value;
|
||||||
|
|
||||||
@ -2093,4 +2100,42 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
|
|||||||
|
|
||||||
return KEY_NULL; // No equivalent key in Raylib
|
return KEY_NULL; // No equivalent key in Raylib
|
||||||
}
|
}
|
||||||
// EOF
|
|
||||||
|
// Get next codepoint in a byte sequence and bytes processed
|
||||||
|
static int GetCodepointNextSDL(const char *text, int *codepointSize)
|
||||||
|
{
|
||||||
|
const char *ptr = text;
|
||||||
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
||||||
|
*codepointSize = 1;
|
||||||
|
|
||||||
|
// Get current codepoint and bytes processed
|
||||||
|
if (0xf0 == (0xf8 & ptr[0]))
|
||||||
|
{
|
||||||
|
// 4 byte UTF-8 codepoint
|
||||||
|
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||||
|
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
|
||||||
|
*codepointSize = 4;
|
||||||
|
}
|
||||||
|
else if (0xe0 == (0xf0 & ptr[0]))
|
||||||
|
{
|
||||||
|
// 3 byte UTF-8 codepoint */
|
||||||
|
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||||
|
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
|
||||||
|
*codepointSize = 3;
|
||||||
|
}
|
||||||
|
else if (0xc0 == (0xe0 & ptr[0]))
|
||||||
|
{
|
||||||
|
// 2 byte UTF-8 codepoint
|
||||||
|
if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } // 10xxxxxx checks
|
||||||
|
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
|
||||||
|
*codepointSize = 2;
|
||||||
|
}
|
||||||
|
else if (0x00 == (0x80 & ptr[0]))
|
||||||
|
{
|
||||||
|
// 1 byte UTF-8 codepoint
|
||||||
|
codepoint = ptr[0];
|
||||||
|
*codepointSize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codepoint;
|
||||||
|
}
|
||||||
|
@ -124,7 +124,7 @@ typedef struct {
|
|||||||
|
|
||||||
// Gamepad data
|
// Gamepad data
|
||||||
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
|
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||||
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXIS][2]; // [0] = min, [1] = range value of the axis
|
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXES][2]; // [0] = min, [1] = range value of the axes
|
||||||
int gamepadAbsAxisMap[MAX_GAMEPADS][ABS_CNT]; // Maps the axes gamepads from the evdev api to a sequential one
|
int gamepadAbsAxisMap[MAX_GAMEPADS][ABS_CNT]; // Maps the axes gamepads from the evdev api to a sequential one
|
||||||
int gamepadCount; // The number of gamepads registered
|
int gamepadCount; // The number of gamepads registered
|
||||||
} PlatformData;
|
} PlatformData;
|
||||||
@ -948,7 +948,7 @@ int InitPlatform(void)
|
|||||||
|
|
||||||
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
||||||
|
|
||||||
EGLConfig *configs = RL_CALLOC(numConfigs, sizeof(*configs));
|
EGLConfig *configs = (EGLConfig *)RL_CALLOC(numConfigs, sizeof(*configs));
|
||||||
if (!configs)
|
if (!configs)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
||||||
@ -1374,7 +1374,7 @@ static void InitEvdevInput(void)
|
|||||||
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
|
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
|
||||||
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
|
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
|
||||||
{
|
{
|
||||||
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
||||||
ConfigureEvdevDevice(path); // Configure the device if appropriate
|
ConfigureEvdevDevice(path); // Configure the device if appropriate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1460,7 +1460,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||||||
// matter if we support them
|
// matter if we support them
|
||||||
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
|
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
|
||||||
|
|
||||||
// If any of the common joystick axis is present, we assume it's a gamepad
|
// If any of the common joystick axes are present, we assume it's a gamepad
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
|
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
|
||||||
@ -1546,7 +1546,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||||||
if (absAxisCount > 0)
|
if (absAxisCount > 0)
|
||||||
{
|
{
|
||||||
// TODO / NOTE
|
// TODO / NOTE
|
||||||
// So gamepad axis (as in the actual linux joydev.c) are just simply enumerated
|
// So gamepad axes (as in the actual linux joydev.c) are just simply enumerated
|
||||||
// and (at least for some input drivers like xpat) it's convention to use
|
// and (at least for some input drivers like xpat) it's convention to use
|
||||||
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the
|
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the
|
||||||
// shoulder buttons
|
// shoulder buttons
|
||||||
@ -1681,7 +1681,7 @@ static void PollGamepadEvents(void)
|
|||||||
|
|
||||||
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: Axis: %2i Value: %i", i, axisRaylib, event.value);
|
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: Axis: %2i Value: %i", i, axisRaylib, event.value);
|
||||||
|
|
||||||
if (axisRaylib < MAX_GAMEPAD_AXIS)
|
if (axisRaylib < MAX_GAMEPAD_AXES)
|
||||||
{
|
{
|
||||||
int min = platform.gamepadAbsAxisRange[i][event.code][0];
|
int min = platform.gamepadAbsAxisRange[i][event.code][0];
|
||||||
int range = platform.gamepadAbsAxisRange[i][event.code][1];
|
int range = platform.gamepadAbsAxisRange[i][event.code][1];
|
||||||
|
@ -1081,7 +1081,7 @@ void PollInputEvents(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register axis data for every connected gamepad
|
// Register axis data for every connected gamepad
|
||||||
for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXIS); j++)
|
for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXES); j++)
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.axisState[i][j] = gamepadState.axis[j];
|
CORE.Input.Gamepad.axisState[i][j] = gamepadState.axis[j];
|
||||||
}
|
}
|
||||||
@ -1746,7 +1746,7 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
|
|||||||
if (gamepadEvent->connected && (gamepadEvent->index < MAX_GAMEPADS))
|
if (gamepadEvent->connected && (gamepadEvent->index < MAX_GAMEPADS))
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
||||||
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index], "%s", gamepadEvent->id);
|
snprintf(CORE.Input.Gamepad.name[gamepadEvent->index], MAX_GAMEPAD_NAME_LENGTH, "%s", gamepadEvent->id);
|
||||||
}
|
}
|
||||||
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
||||||
|
|
||||||
|
55
src/raudio.c
55
src/raudio.c
@ -81,7 +81,7 @@
|
|||||||
#include "utils.h" // Required for: fopen() Android mapping
|
#include "utils.h" // Required for: fopen() Android mapping
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_MODULE_RAUDIO)
|
#if defined(SUPPORT_MODULE_RAUDIO) || defined(RAUDIO_STANDALONE)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// To avoid conflicting windows.h symbols with raylib, some flags are defined
|
// To avoid conflicting windows.h symbols with raylib, some flags are defined
|
||||||
@ -1037,6 +1037,8 @@ void UnloadSoundAlias(Sound alias)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update sound buffer with new data
|
// Update sound buffer with new data
|
||||||
|
// NOTE 1: data format must match sound.stream.sampleSize
|
||||||
|
// NOTE 2: frameCount must not exceed sound.frameCount
|
||||||
void UpdateSound(Sound sound, const void *data, int frameCount)
|
void UpdateSound(Sound sound, const void *data, int frameCount)
|
||||||
{
|
{
|
||||||
if (sound.stream.buffer != NULL)
|
if (sound.stream.buffer != NULL)
|
||||||
@ -1337,7 +1339,7 @@ Music LoadMusicStream(const char *fileName)
|
|||||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
else if (IsFileExtension(fileName, ".wav"))
|
else if (IsFileExtension(fileName, ".wav"))
|
||||||
{
|
{
|
||||||
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
|
||||||
bool success = drwav_init_file(ctxWav, fileName, NULL);
|
bool success = drwav_init_file(ctxWav, fileName, NULL);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
@ -1387,7 +1389,7 @@ Music LoadMusicStream(const char *fileName)
|
|||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
else if (IsFileExtension(fileName, ".mp3"))
|
else if (IsFileExtension(fileName, ".mp3"))
|
||||||
{
|
{
|
||||||
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
|
||||||
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
||||||
|
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
@ -1478,7 +1480,7 @@ Music LoadMusicStream(const char *fileName)
|
|||||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||||
else if (IsFileExtension(fileName, ".mod"))
|
else if (IsFileExtension(fileName, ".mod"))
|
||||||
{
|
{
|
||||||
jar_mod_context_t *ctxMod = RL_CALLOC(1, sizeof(jar_mod_context_t));
|
jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_CALLOC(1, sizeof(jar_mod_context_t));
|
||||||
jar_mod_init(ctxMod);
|
jar_mod_init(ctxMod);
|
||||||
int result = jar_mod_load_file(ctxMod, fileName);
|
int result = jar_mod_load_file(ctxMod, fileName);
|
||||||
|
|
||||||
@ -1529,7 +1531,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
|||||||
#if defined(SUPPORT_FILEFORMAT_WAV)
|
#if defined(SUPPORT_FILEFORMAT_WAV)
|
||||||
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
|
else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
|
||||||
{
|
{
|
||||||
drwav *ctxWav = RL_CALLOC(1, sizeof(drwav));
|
drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
|
||||||
|
|
||||||
bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
|
bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
|
||||||
|
|
||||||
@ -1580,7 +1582,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
|||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||||
{
|
{
|
||||||
drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3));
|
drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
|
||||||
int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
|
int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
@ -1869,6 +1871,7 @@ void SeekMusicStream(Music music, float position)
|
|||||||
void UpdateMusicStream(Music music)
|
void UpdateMusicStream(Music music)
|
||||||
{
|
{
|
||||||
if (music.stream.buffer == NULL) return;
|
if (music.stream.buffer == NULL) return;
|
||||||
|
if (!music.stream.buffer->playing) return;
|
||||||
|
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
|
|
||||||
@ -1888,14 +1891,28 @@ void UpdateMusicStream(Music music)
|
|||||||
// Check both sub-buffers to check if they require refilling
|
// Check both sub-buffers to check if they require refilling
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
|
|
||||||
|
|
||||||
unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
|
unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
|
||||||
unsigned int framesToStream = 0; // Total frames to be streamed
|
unsigned int framesToStream = 0; // Total frames to be streamed
|
||||||
|
|
||||||
if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames;
|
if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames;
|
||||||
else framesToStream = framesLeft;
|
else framesToStream = framesLeft;
|
||||||
|
|
||||||
|
if (framesToStream == 0)
|
||||||
|
{
|
||||||
|
// Check if both buffers have been processed
|
||||||
|
if (music.stream.buffer->isSubBufferProcessed[0] && music.stream.buffer->isSubBufferProcessed[1])
|
||||||
|
{
|
||||||
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
|
StopMusicStream(music);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
|
||||||
|
|
||||||
int frameCountStillNeeded = framesToStream;
|
int frameCountStillNeeded = framesToStream;
|
||||||
int frameCountReadTotal = 0;
|
int frameCountReadTotal = 0;
|
||||||
|
|
||||||
@ -2008,19 +2025,6 @@ void UpdateMusicStream(Music music)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream);
|
UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream);
|
||||||
|
|
||||||
music.stream.buffer->framesProcessed = music.stream.buffer->framesProcessed%music.frameCount;
|
|
||||||
|
|
||||||
if (framesLeft <= subBufferSizeInFrames)
|
|
||||||
{
|
|
||||||
if (!music.looping)
|
|
||||||
{
|
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
|
||||||
// Streaming is ending, we filled latest frames from input
|
|
||||||
StopMusicStream(music);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
@ -2083,8 +2087,12 @@ float GetMusicTimePlayed(Music music)
|
|||||||
int subBufferSize = (int)music.stream.buffer->sizeInFrames/2;
|
int subBufferSize = (int)music.stream.buffer->sizeInFrames/2;
|
||||||
int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize;
|
int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize;
|
||||||
int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize;
|
int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize;
|
||||||
|
int framesInBuffers = framesInFirstBuffer + framesInSecondBuffer;
|
||||||
|
if (framesInBuffers > music.frameCount) {
|
||||||
|
if (!music.looping) framesInBuffers = music.frameCount;
|
||||||
|
}
|
||||||
int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize;
|
int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize;
|
||||||
int framesPlayed = (framesProcessed - framesInFirstBuffer - framesInSecondBuffer + framesSentToMix)%(int)music.frameCount;
|
int framesPlayed = (framesProcessed - framesInBuffers + framesSentToMix)%(int)music.frameCount;
|
||||||
if (framesPlayed < 0) framesPlayed += music.frameCount;
|
if (framesPlayed < 0) framesPlayed += music.frameCount;
|
||||||
secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
|
secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
@ -2681,8 +2689,7 @@ static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data,
|
|||||||
ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;
|
ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;
|
||||||
unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
|
unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
|
||||||
|
|
||||||
// Total frames processed in buffer is always the complete size, filled with 0 if required
|
stream.buffer->framesProcessed += frameCount;
|
||||||
stream.buffer->framesProcessed += subBufferSizeInFrames;
|
|
||||||
|
|
||||||
// Does this API expect a whole buffer to be updated in one go?
|
// Does this API expect a whole buffer to be updated in one go?
|
||||||
// Assuming so, but if not will need to change this logic
|
// Assuming so, but if not will need to change this logic
|
||||||
|
28
src/raylib.h
28
src/raylib.h
@ -743,7 +743,7 @@ typedef enum {
|
|||||||
GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right
|
GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right
|
||||||
} GamepadButton;
|
} GamepadButton;
|
||||||
|
|
||||||
// Gamepad axis
|
// Gamepad axes
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis
|
GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis
|
||||||
GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis
|
GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis
|
||||||
@ -954,7 +954,7 @@ typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args);
|
|||||||
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
|
||||||
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
@ -1123,7 +1123,7 @@ RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save
|
|||||||
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
|
||||||
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
|
||||||
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
|
||||||
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
RLAPI bool SaveFileText(const char *fileName, const char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
// File system functions
|
// File system functions
|
||||||
@ -1153,8 +1153,8 @@ RLAPI long GetFileModTime(const char *fileName); // Get file mo
|
|||||||
// Compression/Encoding functionality
|
// Compression/Encoding functionality
|
||||||
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
|
RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress 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 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 (includes NULL terminator), 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 char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree()
|
||||||
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
|
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 *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)
|
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||||
@ -1192,8 +1192,8 @@ RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a game
|
|||||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
||||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
||||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||||
RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad
|
RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad
|
||||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis
|
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get movement value for a gamepad axis
|
||||||
RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
|
RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
|
||||||
RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
|
RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
|
||||||
|
|
||||||
@ -1264,7 +1264,9 @@ RLAPI void DrawCircleV(Vector2 center, float radius, Color color);
|
|||||||
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
|
||||||
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
|
||||||
|
RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version)
|
||||||
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
|
||||||
|
RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version)
|
||||||
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
|
||||||
RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
|
RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
|
||||||
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
||||||
@ -1273,7 +1275,7 @@ RLAPI void DrawRectangleRec(Rectangle rec, Color color);
|
|||||||
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
|
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
|
||||||
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
|
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
|
||||||
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
|
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
|
||||||
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors
|
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight); // Draw a gradient-filled rectangle with custom vertex colors
|
||||||
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
||||||
RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
|
RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
|
||||||
RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
|
RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
|
||||||
@ -1406,8 +1408,8 @@ RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color c
|
|||||||
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
|
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
|
||||||
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
|
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
|
||||||
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
|
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
|
||||||
RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
|
RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
|
||||||
RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
|
RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
|
||||||
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
|
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
|
||||||
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
|
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
|
||||||
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
|
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
|
||||||
@ -1422,8 +1424,8 @@ RLAPI bool IsTextureValid(Texture2D texture);
|
|||||||
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
||||||
RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
|
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 (pixels should be able to fill texture)
|
||||||
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 (pixels and rec should fit in texture)
|
||||||
|
|
||||||
// Texture configuration functions
|
// Texture configuration functions
|
||||||
RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
|
RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
|
||||||
@ -1644,7 +1646,7 @@ RLAPI Sound LoadSound(const char *fileName); // Load so
|
|||||||
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 IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
|
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 (data and frame count should fit in sound)
|
||||||
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
|
||||||
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
|
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
|
||||||
|
260
src/rcore.c
260
src/rcore.c
@ -235,10 +235,10 @@ __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod)
|
|||||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_GAMEPAD_NAME_LENGTH
|
#ifndef MAX_GAMEPAD_NAME_LENGTH
|
||||||
#define MAX_GAMEPAD_NAME_LENGTH 128 // Maximum number of characters of gamepad name (byte size)
|
#define MAX_GAMEPAD_NAME_LENGTH 128 // Maximum number of characters in a gamepad name (byte size)
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_GAMEPAD_AXIS
|
#ifndef MAX_GAMEPAD_AXES
|
||||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
#define MAX_GAMEPAD_AXES 8 // Maximum number of axes supported (per gamepad)
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_GAMEPAD_BUTTONS
|
#ifndef MAX_GAMEPAD_BUTTONS
|
||||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||||
@ -354,12 +354,12 @@ typedef struct CoreData {
|
|||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
int lastButtonPressed; // Register last gamepad button pressed
|
int lastButtonPressed; // Register last gamepad button pressed
|
||||||
int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axis
|
int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axes
|
||||||
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
|
bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
|
||||||
char name[MAX_GAMEPADS][MAX_GAMEPAD_NAME_LENGTH]; // Gamepad name holder
|
char name[MAX_GAMEPADS][MAX_GAMEPAD_NAME_LENGTH]; // Gamepad name holder
|
||||||
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
|
||||||
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
char previousButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
|
||||||
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
|
float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXES]; // Gamepad axes state
|
||||||
|
|
||||||
} Gamepad;
|
} Gamepad;
|
||||||
} Input;
|
} Input;
|
||||||
@ -523,25 +523,25 @@ const char *TextFormat(const char *text, ...); // Formatting of tex
|
|||||||
#define PLATFORM_DESKTOP_GLFW
|
#define PLATFORM_DESKTOP_GLFW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We're using `#pragma message` because `#warning` is not adopted by MSVC.
|
// We're using '#pragma message' because '#warning' is not adopted by MSVC
|
||||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||||
#if !defined(SUPPORT_MODULE_RTEXTURES)
|
#if !defined(SUPPORT_MODULE_RTEXTURES)
|
||||||
#pragma message ("Warning: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly")
|
#pragma message ("WARNING: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// It's nice to have support Bitmap on Linux as well, but not as necessary as Windows
|
// It's nice to have support Bitmap on Linux as well, but not as necessary as Windows
|
||||||
#if !defined(SUPPORT_FILEFORMAT_BMP) && defined(_WIN32)
|
#if !defined(SUPPORT_FILEFORMAT_BMP) && defined(_WIN32)
|
||||||
#pragma message ("Warning: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_FILEFORMAT_BMP, specially on Windows")
|
#pragma message ("WARNING: Enabling SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_FILEFORMAT_BMP, specially on Windows")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// From what I've tested applications on Wayland saves images on clipboard as PNG.
|
// From what I've tested applications on Wayland saves images on clipboard as PNG
|
||||||
#if (!defined(SUPPORT_FILEFORMAT_PNG) || !defined(SUPPORT_FILEFORMAT_JPG)) && !defined(_WIN32)
|
#if (!defined(SUPPORT_FILEFORMAT_PNG) || !defined(SUPPORT_FILEFORMAT_JPG)) && !defined(_WIN32)
|
||||||
#pragma message ("Warning: Getting image from the clipboard might not work without SUPPORT_FILEFORMAT_PNG or SUPPORT_FILEFORMAT_JPG")
|
#pragma message ("WARNING: Getting image from the clipboard might not work without SUPPORT_FILEFORMAT_PNG or SUPPORT_FILEFORMAT_JPG")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Not needed because `rtexture.c` will automatically defined STBI_REQUIRED when any SUPPORT_FILEFORMAT_* is defined.
|
// Not needed because `rtexture.c` will automatically defined STBI_REQUIRED when any SUPPORT_FILEFORMAT_* is defined
|
||||||
// #if !defined(STBI_REQUIRED)
|
// #if !defined(STBI_REQUIRED)
|
||||||
// #pragma message ("Warning: "STBI_REQUIRED is not defined, that means we can't load images from clipbard"
|
// #pragma message ("WARNING: "STBI_REQUIRED is not defined, that means we can't load images from clipbard"
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||||
@ -2313,11 +2313,14 @@ FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool
|
|||||||
// Unload directory filepaths
|
// Unload directory filepaths
|
||||||
// WARNING: files.count is not reseted to 0 after unloading
|
// WARNING: files.count is not reseted to 0 after unloading
|
||||||
void UnloadDirectoryFiles(FilePathList files)
|
void UnloadDirectoryFiles(FilePathList files)
|
||||||
|
{
|
||||||
|
if (files.paths != NULL)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
||||||
|
|
||||||
RL_FREE(files.paths);
|
RL_FREE(files.paths);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create directories (including full path requested), returns 0 on success
|
// Create directories (including full path requested), returns 0 on success
|
||||||
int MakeDirectory(const char *dirPath)
|
int MakeDirectory(const char *dirPath)
|
||||||
@ -2497,7 +2500,7 @@ unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDa
|
|||||||
|
|
||||||
#if defined(SUPPORT_COMPRESSION_API)
|
#if defined(SUPPORT_COMPRESSION_API)
|
||||||
// Compress data and generate a valid DEFLATE stream
|
// Compress data and generate a valid DEFLATE stream
|
||||||
struct sdefl *sdefl = RL_CALLOC(1, sizeof(struct sdefl)); // WARNING: Possible stack overflow, struct sdefl is almost 1MB
|
struct sdefl *sdefl = (struct sdefl *)RL_CALLOC(1, sizeof(struct sdefl)); // WARNING: Possible stack overflow, struct sdefl is almost 1MB
|
||||||
int bounds = sdefl_bound(dataSize);
|
int bounds = sdefl_bound(dataSize);
|
||||||
compData = (unsigned char *)RL_CALLOC(bounds, 1);
|
compData = (unsigned char *)RL_CALLOC(bounds, 1);
|
||||||
|
|
||||||
@ -2536,96 +2539,112 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encode data to Base64 string
|
// Encode data to Base64 string
|
||||||
|
// NOTE: Returned string includes NULL terminator, considered on outputSize
|
||||||
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
||||||
{
|
{
|
||||||
static const unsigned char base64encodeTable[] = {
|
// Base64 conversion table from RFC 4648 [0..63]
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
// NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sixtets" (6bit characters)
|
||||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
static const char base64EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int modTable[] = { 0, 2, 1 };
|
// Compute expected size and padding
|
||||||
|
int paddedSize = dataSize;
|
||||||
|
while (paddedSize%3 != 0) paddedSize++; // Padding bytes to round 4*(dataSize/3) to 4 bytes
|
||||||
|
int estimatedOutputSize = 4*(paddedSize/3);
|
||||||
|
int padding = paddedSize - dataSize;
|
||||||
|
|
||||||
*outputSize = 4*((dataSize + 2)/3);
|
// Adding null terminator to string
|
||||||
|
estimatedOutputSize += 1;
|
||||||
|
|
||||||
char *encodedData = (char *)RL_MALLOC(*outputSize);
|
// Load some memory to store encoded string
|
||||||
|
char *encodedData = (char *)RL_CALLOC(estimatedOutputSize, 1);
|
||||||
|
if (encodedData == NULL) return NULL;
|
||||||
|
|
||||||
if (encodedData == NULL) return NULL; // Security check
|
int outputCount = 0;
|
||||||
|
for (int i = 0; i < dataSize;)
|
||||||
for (int i = 0, j = 0; i < dataSize;)
|
|
||||||
{
|
{
|
||||||
unsigned int octetA = (i < dataSize)? (unsigned char)data[i++] : 0;
|
unsigned int octetA = 0;
|
||||||
unsigned int octetB = (i < dataSize)? (unsigned char)data[i++] : 0;
|
unsigned int octetB = 0;
|
||||||
unsigned int octetC = (i < dataSize)? (unsigned char)data[i++] : 0;
|
unsigned int octetC = 0;
|
||||||
|
unsigned int octetPack = 0;
|
||||||
|
|
||||||
unsigned int triple = (octetA << 0x10) + (octetB << 0x08) + octetC;
|
octetA = data[i]; // Generates 2 sextets
|
||||||
|
octetB = ((i + 1) < dataSize)? data[i + 1] : 0; // Generates 3 sextets
|
||||||
|
octetC = ((i + 2) < dataSize)? data[i + 2] : 0; // Generates 4 sextets
|
||||||
|
|
||||||
encodedData[j++] = base64encodeTable[(triple >> 3*6) & 0x3F];
|
octetPack = (octetA << 16) | (octetB << 8) | octetC;
|
||||||
encodedData[j++] = base64encodeTable[(triple >> 2*6) & 0x3F];
|
|
||||||
encodedData[j++] = base64encodeTable[(triple >> 1*6) & 0x3F];
|
encodedData[outputCount + 0] = (unsigned char)(base64EncodeTable[(octetPack >> 18) & 0x3f]);
|
||||||
encodedData[j++] = base64encodeTable[(triple >> 0*6) & 0x3F];
|
encodedData[outputCount + 1] = (unsigned char)(base64EncodeTable[(octetPack >> 12) & 0x3f]);
|
||||||
|
encodedData[outputCount + 2] = (unsigned char)(base64EncodeTable[(octetPack >> 6) & 0x3f]);
|
||||||
|
encodedData[outputCount + 3] = (unsigned char)(base64EncodeTable[octetPack & 0x3f]);
|
||||||
|
outputCount += 4;
|
||||||
|
i += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < modTable[dataSize%3]; i++) encodedData[*outputSize - 1 - i] = '='; // Padding character
|
// Add required padding bytes
|
||||||
|
for (int p = 0; p < padding; p++) encodedData[outputCount - p - 1] = '=';
|
||||||
|
|
||||||
|
// Add null terminator to string
|
||||||
|
encodedData[outputCount] = '\0';
|
||||||
|
outputCount++;
|
||||||
|
|
||||||
|
if (outputCount != estimatedOutputSize) TRACELOG(LOG_WARNING, "BASE64: Output size differs from estimation");
|
||||||
|
|
||||||
|
*outputSize = estimatedOutputSize;
|
||||||
return encodedData;
|
return encodedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode Base64 string data
|
// Decode Base64 string (expected NULL terminated)
|
||||||
unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
unsigned char *DecodeDataBase64(const char *text, int *outputSize)
|
||||||
{
|
{
|
||||||
static const unsigned char base64decodeTable[] = {
|
// Base64 decode table
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
// NOTE: Following ASCII order [0..255] assigning the expected sixtet value to
|
||||||
0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
// every character in the corresponding ASCII position
|
||||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
|
static const unsigned char base64DecodeTable[256] = {
|
||||||
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
|
||||||
|
['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
|
||||||
|
['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, ['Z'] = 25,
|
||||||
|
['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33,
|
||||||
|
['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41,
|
||||||
|
['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51,
|
||||||
|
['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
|
||||||
|
['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get output size of Base64 input data
|
// Compute expected size and padding
|
||||||
int outSize = 0;
|
int dataSize = (int)strlen(text); // WARNING: Expecting NULL terminated strings!
|
||||||
for (int i = 0; data[4*i] != 0; i++)
|
int ending = dataSize - 1;
|
||||||
|
int padding = 0;
|
||||||
|
while (text[ending] == '=') { padding++; ending--; }
|
||||||
|
int estimatedOutputSize = 3*(dataSize/4) - padding;
|
||||||
|
int maxOutputSize = 3*(dataSize/4);
|
||||||
|
|
||||||
|
// Load some memory to store decoded data
|
||||||
|
// NOTE: Allocated enough size to include padding
|
||||||
|
unsigned char *decodedData = (unsigned char *)RL_CALLOC(maxOutputSize, 1);
|
||||||
|
if (decodedData == NULL) return NULL;
|
||||||
|
|
||||||
|
int outputCount = 0;
|
||||||
|
for (int i = 0; i < dataSize;)
|
||||||
{
|
{
|
||||||
if (data[4*i + 3] == '=')
|
// Every 4 sixtets must generate 3 octets
|
||||||
{
|
unsigned int sixtetA = base64DecodeTable[(unsigned char)text[i]];
|
||||||
if (data[4*i + 2] == '=') outSize += 1;
|
unsigned int sixtetB = base64DecodeTable[(unsigned char)text[i + 1]];
|
||||||
else outSize += 2;
|
unsigned int sixtetC = ((unsigned char)text[i + 2] != '=')? base64DecodeTable[(unsigned char)text[i + 2]] : 0;
|
||||||
}
|
unsigned int sixtetD = ((unsigned char)text[i + 3] != '=')? base64DecodeTable[(unsigned char)text[i + 3]] : 0;
|
||||||
else outSize += 3;
|
|
||||||
|
unsigned int octetPack = (sixtetA << 18) | (sixtetB << 12) | (sixtetC << 6) | sixtetD;
|
||||||
|
|
||||||
|
decodedData[outputCount + 0] = (octetPack >> 16) & 0xff;
|
||||||
|
decodedData[outputCount + 1] = (octetPack >> 8) & 0xff;
|
||||||
|
decodedData[outputCount + 2] = octetPack & 0xff;
|
||||||
|
outputCount += 3;
|
||||||
|
i += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory to store decoded Base64 data
|
if (estimatedOutputSize != (outputCount - padding)) TRACELOG(LOG_WARNING, "BASE64: Decoded size differs from estimation");
|
||||||
unsigned char *decodedData = (unsigned char *)RL_MALLOC(outSize);
|
|
||||||
|
|
||||||
for (int i = 0; i < outSize/3; i++)
|
*outputSize = estimatedOutputSize;
|
||||||
{
|
|
||||||
unsigned char a = base64decodeTable[(int)data[4*i]];
|
|
||||||
unsigned char b = base64decodeTable[(int)data[4*i + 1]];
|
|
||||||
unsigned char c = base64decodeTable[(int)data[4*i + 2]];
|
|
||||||
unsigned char d = base64decodeTable[(int)data[4*i + 3]];
|
|
||||||
|
|
||||||
decodedData[3*i] = (a << 2) | (b >> 4);
|
|
||||||
decodedData[3*i + 1] = (b << 4) | (c >> 2);
|
|
||||||
decodedData[3*i + 2] = (c << 6) | d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outSize%3 == 1)
|
|
||||||
{
|
|
||||||
int n = outSize/3;
|
|
||||||
unsigned char a = base64decodeTable[(int)data[4*n]];
|
|
||||||
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
|
||||||
decodedData[outSize - 1] = (a << 2) | (b >> 4);
|
|
||||||
}
|
|
||||||
else if (outSize%3 == 2)
|
|
||||||
{
|
|
||||||
int n = outSize/3;
|
|
||||||
unsigned char a = base64decodeTable[(int)data[4*n]];
|
|
||||||
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
|
||||||
unsigned char c = base64decodeTable[(int)data[4*n + 2]];
|
|
||||||
decodedData[outSize - 2] = (a << 2) | (b >> 4);
|
|
||||||
decodedData[outSize - 1] = (b << 4) | (c >> 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
*outputSize = outSize;
|
|
||||||
return decodedData;
|
return decodedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2633,38 +2652,38 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
|||||||
unsigned int ComputeCRC32(unsigned char *data, int dataSize)
|
unsigned int ComputeCRC32(unsigned char *data, int dataSize)
|
||||||
{
|
{
|
||||||
static unsigned int crcTable[256] = {
|
static unsigned int crcTable[256] = {
|
||||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||||
0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int crc = ~0u;
|
unsigned int crc = ~0u;
|
||||||
@ -2728,7 +2747,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
|||||||
|
|
||||||
int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
|
int newDataSize = ((((dataSize + 8)/64) + 1)*64) - 8;
|
||||||
|
|
||||||
unsigned char *msg = RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
|
unsigned char *msg = (unsigned char *)RL_CALLOC(newDataSize + 64, 1); // Initialize with '0' bits, allocating 64 extra bytes
|
||||||
memcpy(msg, data, dataSize);
|
memcpy(msg, data, dataSize);
|
||||||
msg[dataSize] = 128; // Write the '1' bit
|
msg[dataSize] = 128; // Write the '1' bit
|
||||||
|
|
||||||
@ -2818,7 +2837,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
|
|||||||
|
|
||||||
int newDataSize = ((((dataSize + 8)/64) + 1)*64);
|
int newDataSize = ((((dataSize + 8)/64) + 1)*64);
|
||||||
|
|
||||||
unsigned char *msg = RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
|
unsigned char *msg = (unsigned char *)RL_CALLOC(newDataSize, 1); // Initialize with '0' bits
|
||||||
memcpy(msg, data, dataSize);
|
memcpy(msg, data, dataSize);
|
||||||
msg[dataSize] = 128; // Write the '1' bit
|
msg[dataSize] = 128; // Write the '1' bit
|
||||||
|
|
||||||
@ -3349,11 +3368,11 @@ int GetGamepadAxisCount(int gamepad)
|
|||||||
// Get axis movement vector for a gamepad
|
// Get axis movement vector for a gamepad
|
||||||
float GetGamepadAxisMovement(int gamepad, int axis)
|
float GetGamepadAxisMovement(int gamepad, int axis)
|
||||||
{
|
{
|
||||||
float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
|
float value = ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))? -1.0f : 0.0f;
|
||||||
|
|
||||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS))
|
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXES))
|
||||||
{
|
{
|
||||||
float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
|
float movement = (value < 0.0f)? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
|
||||||
|
|
||||||
if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis];
|
if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis];
|
||||||
}
|
}
|
||||||
@ -3738,6 +3757,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
|||||||
// Scan all files and directories recursively from a base path
|
// Scan all files and directories recursively from a base path
|
||||||
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
|
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
|
||||||
{
|
{
|
||||||
|
// WARNING: Path can not be static or it will be reused between recursive function calls!
|
||||||
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
char path[MAX_FILEPATH_LENGTH] = { 0 };
|
||||||
memset(path, 0, MAX_FILEPATH_LENGTH);
|
memset(path, 0, MAX_FILEPATH_LENGTH);
|
||||||
|
|
||||||
@ -4031,10 +4051,10 @@ static void RecordAutomationEvent(void)
|
|||||||
if (currentEventList->count == currentEventList->capacity) return; // Security check
|
if (currentEventList->count == currentEventList->capacity) return; // Security check
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++)
|
for (int axis = 0; axis < MAX_GAMEPAD_AXES; axis++)
|
||||||
{
|
{
|
||||||
// Event type: INPUT_GAMEPAD_AXIS_MOTION
|
// Event type: INPUT_GAMEPAD_AXIS_MOTION
|
||||||
float defaultMovement = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
|
float defaultMovement = ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))? -1.0f : 0.0f;
|
||||||
if (GetGamepadAxisMovement(gamepad, axis) != defaultMovement)
|
if (GetGamepadAxisMovement(gamepad, axis) != defaultMovement)
|
||||||
{
|
{
|
||||||
currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;
|
currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter;
|
||||||
|
32
src/rlgl.h
32
src/rlgl.h
@ -56,8 +56,8 @@
|
|||||||
*
|
*
|
||||||
* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
|
* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
|
||||||
* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
|
* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
|
||||||
* #define RL_CULL_DISTANCE_NEAR 0.001 // Default projection matrix near cull distance
|
* #define RL_CULL_DISTANCE_NEAR 0.05 // Default projection matrix near cull distance
|
||||||
* #define RL_CULL_DISTANCE_FAR 10000.0 // Default projection matrix far cull distance
|
* #define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance
|
||||||
*
|
*
|
||||||
* When loading a shader, the following vertex attributes and uniform
|
* When loading a shader, the following vertex attributes and uniform
|
||||||
* location names are tried to be set automatically:
|
* location names are tried to be set automatically:
|
||||||
@ -234,10 +234,10 @@
|
|||||||
|
|
||||||
// Projection matrix culling
|
// Projection matrix culling
|
||||||
#ifndef RL_CULL_DISTANCE_NEAR
|
#ifndef RL_CULL_DISTANCE_NEAR
|
||||||
#define RL_CULL_DISTANCE_NEAR 0.001 // Default near cull distance
|
#define RL_CULL_DISTANCE_NEAR 0.05 // Default near cull distance
|
||||||
#endif
|
#endif
|
||||||
#ifndef RL_CULL_DISTANCE_FAR
|
#ifndef RL_CULL_DISTANCE_FAR
|
||||||
#define RL_CULL_DISTANCE_FAR 10000.0 // Default far cull distance
|
#define RL_CULL_DISTANCE_FAR 4000.0 // Default far cull distance
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Texture parameters (equivalent to OpenGL defines)
|
// Texture parameters (equivalent to OpenGL defines)
|
||||||
@ -1748,7 +1748,6 @@ void rlTextureParameters(unsigned int id, int param, int value)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else glTexParameteri(GL_TEXTURE_2D, param, value);
|
else glTexParameteri(GL_TEXTURE_2D, param, value);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_TEXTURE_MAG_FILTER:
|
case RL_TEXTURE_MAG_FILTER:
|
||||||
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
|
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
|
||||||
@ -1793,7 +1792,6 @@ void rlCubemapParameters(unsigned int id, int param, int value)
|
|||||||
else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
|
else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
|
||||||
}
|
}
|
||||||
else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
|
else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_TEXTURE_MAG_FILTER:
|
case RL_TEXTURE_MAG_FILTER:
|
||||||
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break;
|
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break;
|
||||||
@ -1887,7 +1885,7 @@ void rlActiveDrawBuffers(int count)
|
|||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
|
if (count > 8) TRACELOG(RL_LOG_WARNING, "GL: Max color buffers limited to 8");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int buffers[8] = {
|
unsigned int buffers[8] = {
|
||||||
@ -1904,7 +1902,7 @@ void rlActiveDrawBuffers(int count)
|
|||||||
glDrawBuffers(count, buffers);
|
glDrawBuffers(count, buffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
else TRACELOG(RL_LOG_WARNING, "GL: One color buffer active by default");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2112,14 +2110,12 @@ void rlSetBlendMode(int mode)
|
|||||||
{
|
{
|
||||||
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
|
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
|
||||||
glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
|
glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_BLEND_CUSTOM_SEPARATE:
|
case RL_BLEND_CUSTOM_SEPARATE:
|
||||||
{
|
{
|
||||||
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate()
|
// NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate()
|
||||||
glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha);
|
glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha);
|
||||||
glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha);
|
glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -2223,10 +2219,10 @@ static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_WARNING, "GL: OpenGL debug message: %s", message);
|
TRACELOG(RL_LOG_WARNING, "GL: OpenGL debug message: %s", message);
|
||||||
TRACELOG(LOG_WARNING, " > Type: %s", msgType);
|
TRACELOG(RL_LOG_WARNING, " > Type: %s", msgType);
|
||||||
TRACELOG(LOG_WARNING, " > Source = %s", msgSource);
|
TRACELOG(RL_LOG_WARNING, " > Source = %s", msgSource);
|
||||||
TRACELOG(LOG_WARNING, " > Severity = %s", msgSeverity);
|
TRACELOG(RL_LOG_WARNING, " > Severity = %s", msgSeverity);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2429,7 +2425,7 @@ void rlLoadExtensions(void *loader)
|
|||||||
|
|
||||||
// Get supported extensions list
|
// Get supported extensions list
|
||||||
GLint numExt = 0;
|
GLint numExt = 0;
|
||||||
const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
|
const char **extList = (const char **)RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
|
||||||
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
||||||
|
|
||||||
// NOTE: We have to duplicate string because glGetString() returns a const string
|
// NOTE: We have to duplicate string because glGetString() returns a const string
|
||||||
@ -3747,19 +3743,16 @@ void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType,
|
|||||||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel);
|
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel);
|
||||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId);
|
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId);
|
||||||
else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel);
|
else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_ATTACHMENT_DEPTH:
|
case RL_ATTACHMENT_DEPTH:
|
||||||
{
|
{
|
||||||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
||||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId);
|
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_ATTACHMENT_STENCIL:
|
case RL_ATTACHMENT_STENCIL:
|
||||||
{
|
{
|
||||||
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
|
||||||
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId);
|
else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -4185,6 +4178,9 @@ unsigned int rlCompileShader(const char *shaderCode, int type)
|
|||||||
RL_FREE(log);
|
RL_FREE(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unload object allocated by glCreateShader(),
|
||||||
|
// despite failing in the compilation process
|
||||||
|
glDeleteShader(shader);
|
||||||
shader = 0;
|
shader = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
382
src/rmodels.c
382
src/rmodels.c
@ -496,12 +496,18 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
|
|||||||
vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis
|
vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis
|
||||||
vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z };
|
vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z };
|
||||||
|
|
||||||
|
rlNormal3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||||
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||||
|
rlNormal3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
||||||
rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
||||||
|
rlNormal3f(vertices[1].x, vertices[1].y, vertices[1].z);
|
||||||
rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z);
|
rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z);
|
||||||
|
|
||||||
|
rlNormal3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||||
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||||
|
rlNormal3f(vertices[2].x, vertices[2].y, vertices[2].z);
|
||||||
rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z);
|
rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z);
|
||||||
|
rlNormal3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
||||||
rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1423,9 +1429,13 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
|
|||||||
|
|
||||||
rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);
|
rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);
|
||||||
|
|
||||||
rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);
|
if (mesh.animVertices) rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.animVertices);
|
||||||
|
else rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);
|
||||||
|
|
||||||
rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
|
rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
|
||||||
rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
|
if (mesh.normals) rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.animNormals);
|
||||||
|
else rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
|
||||||
|
|
||||||
rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
|
rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
|
||||||
|
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
@ -2164,7 +2174,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
|
|||||||
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
|
||||||
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
|
||||||
|
|
||||||
materials = RL_MALLOC(count*sizeof(Material));
|
materials = (Material *)RL_MALLOC(count*sizeof(Material));
|
||||||
ProcessMaterialsOBJ(materials, mats, count);
|
ProcessMaterialsOBJ(materials, mats, count);
|
||||||
|
|
||||||
tinyobj_materials_free(mats, count);
|
tinyobj_materials_free(mats, count);
|
||||||
@ -3598,16 +3608,16 @@ BoundingBox GetMeshBoundingBox(Mesh mesh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute mesh tangents
|
// Compute mesh tangents
|
||||||
// NOTE: To calculate mesh tangents and binormals we need mesh vertex positions and texture coordinates
|
|
||||||
// Implementation based on: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html
|
|
||||||
void GenMeshTangents(Mesh *mesh)
|
void GenMeshTangents(Mesh *mesh)
|
||||||
{
|
{
|
||||||
if ((mesh->vertices == NULL) || (mesh->texcoords == NULL))
|
// Check if input mesh data is useful
|
||||||
|
if ((mesh == NULL) || (mesh->vertices == NULL) || (mesh->texcoords == NULL) || (mesh->normals == NULL))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MESH: Tangents generation requires texcoord vertex attribute data");
|
TRACELOG(LOG_WARNING, "MESH: Tangents generation requires vertices, texcoords and normals vertex attribute data");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate or reallocate tangents data
|
||||||
if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
|
if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3615,26 +3625,51 @@ void GenMeshTangents(Mesh *mesh)
|
|||||||
mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
|
mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 *tan1 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));
|
// Allocate temporary arrays for tangents calculation
|
||||||
Vector3 *tan2 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));
|
Vector3 *tan1 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
|
||||||
|
Vector3 *tan2 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
|
||||||
|
|
||||||
if (mesh->vertexCount % 3 != 0)
|
if (tan1 == NULL || tan2 == NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "MESH: vertexCount expected to be a multiple of 3. Expect uninitialized values.");
|
TRACELOG(LOG_WARNING, "MESH: Failed to allocate temporary memory for tangent calculation");
|
||||||
|
if (tan1) RL_FREE(tan1);
|
||||||
|
if (tan2) RL_FREE(tan2);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i <= mesh->vertexCount - 3; i += 3)
|
// Process all triangles of the mesh
|
||||||
|
// 'triangleCount' must be always valid
|
||||||
|
for (int t = 0; t < mesh->triangleCount; t++)
|
||||||
{
|
{
|
||||||
// Get triangle vertices
|
// Get triangle vertex indices
|
||||||
Vector3 v1 = { mesh->vertices[(i + 0)*3 + 0], mesh->vertices[(i + 0)*3 + 1], mesh->vertices[(i + 0)*3 + 2] };
|
int i0, i1, i2;
|
||||||
Vector3 v2 = { mesh->vertices[(i + 1)*3 + 0], mesh->vertices[(i + 1)*3 + 1], mesh->vertices[(i + 1)*3 + 2] };
|
|
||||||
Vector3 v3 = { mesh->vertices[(i + 2)*3 + 0], mesh->vertices[(i + 2)*3 + 1], mesh->vertices[(i + 2)*3 + 2] };
|
if (mesh->indices != NULL)
|
||||||
|
{
|
||||||
|
// Use indices if available
|
||||||
|
i0 = mesh->indices[t*3 + 0];
|
||||||
|
i1 = mesh->indices[t*3 + 1];
|
||||||
|
i2 = mesh->indices[t*3 + 2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Sequential access for non-indexed mesh
|
||||||
|
i0 = t*3 + 0;
|
||||||
|
i1 = t*3 + 1;
|
||||||
|
i2 = t*3 + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get triangle vertices position
|
||||||
|
Vector3 v1 = { mesh->vertices[i0*3 + 0], mesh->vertices[i0*3 + 1], mesh->vertices[i0*3 + 2] };
|
||||||
|
Vector3 v2 = { mesh->vertices[i1*3 + 0], mesh->vertices[i1*3 + 1], mesh->vertices[i1*3 + 2] };
|
||||||
|
Vector3 v3 = { mesh->vertices[i2*3 + 0], mesh->vertices[i2*3 + 1], mesh->vertices[i2*3 + 2] };
|
||||||
|
|
||||||
// Get triangle texcoords
|
// Get triangle texcoords
|
||||||
Vector2 uv1 = { mesh->texcoords[(i + 0)*2 + 0], mesh->texcoords[(i + 0)*2 + 1] };
|
Vector2 uv1 = { mesh->texcoords[i0*2 + 0], mesh->texcoords[i0*2 + 1] };
|
||||||
Vector2 uv2 = { mesh->texcoords[(i + 1)*2 + 0], mesh->texcoords[(i + 1)*2 + 1] };
|
Vector2 uv2 = { mesh->texcoords[i1*2 + 0], mesh->texcoords[i1*2 + 1] };
|
||||||
Vector2 uv3 = { mesh->texcoords[(i + 2)*2 + 0], mesh->texcoords[(i + 2)*2 + 1] };
|
Vector2 uv3 = { mesh->texcoords[i2*2 + 0], mesh->texcoords[i2*2 + 1] };
|
||||||
|
|
||||||
|
// Calculate triangle edges
|
||||||
float x1 = v2.x - v1.x;
|
float x1 = v2.x - v1.x;
|
||||||
float y1 = v2.y - v1.y;
|
float y1 = v2.y - v1.y;
|
||||||
float z1 = v2.z - v1.z;
|
float z1 = v2.z - v1.z;
|
||||||
@ -3642,65 +3677,95 @@ void GenMeshTangents(Mesh *mesh)
|
|||||||
float y2 = v3.y - v1.y;
|
float y2 = v3.y - v1.y;
|
||||||
float z2 = v3.z - v1.z;
|
float z2 = v3.z - v1.z;
|
||||||
|
|
||||||
|
// Calculate texture coordinate differences
|
||||||
float s1 = uv2.x - uv1.x;
|
float s1 = uv2.x - uv1.x;
|
||||||
float t1 = uv2.y - uv1.y;
|
float t1 = uv2.y - uv1.y;
|
||||||
float s2 = uv3.x - uv1.x;
|
float s2 = uv3.x - uv1.x;
|
||||||
float t2 = uv3.y - uv1.y;
|
float t2 = uv3.y - uv1.y;
|
||||||
|
|
||||||
|
// Calculate denominator and check for degenerate UV
|
||||||
float div = s1*t2 - s2*t1;
|
float div = s1*t2 - s2*t1;
|
||||||
float r = (div == 0.0f)? 0.0f : 1.0f/div;
|
float r = (fabsf(div) < 0.0001f)? 0.0f : 1.0f/div;
|
||||||
|
|
||||||
|
// Calculate tangent and bitangent directions
|
||||||
Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };
|
Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };
|
||||||
Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };
|
Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };
|
||||||
|
|
||||||
tan1[i + 0] = sdir;
|
// Accumulate tangents and bitangents for each vertex of the triangle
|
||||||
tan1[i + 1] = sdir;
|
tan1[i0] = Vector3Add(tan1[i0], sdir);
|
||||||
tan1[i + 2] = sdir;
|
tan1[i1] = Vector3Add(tan1[i1], sdir);
|
||||||
|
tan1[i2] = Vector3Add(tan1[i2], sdir);
|
||||||
|
|
||||||
tan2[i + 0] = tdir;
|
tan2[i0] = Vector3Add(tan2[i0], tdir);
|
||||||
tan2[i + 1] = tdir;
|
tan2[i1] = Vector3Add(tan2[i1], tdir);
|
||||||
tan2[i + 2] = tdir;
|
tan2[i2] = Vector3Add(tan2[i2], tdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute tangents considering normals
|
// Calculate final tangents for each vertex
|
||||||
for (int i = 0; i < mesh->vertexCount; i++)
|
for (int i = 0; i < mesh->vertexCount; i++)
|
||||||
{
|
{
|
||||||
Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };
|
Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };
|
||||||
Vector3 tangent = tan1[i];
|
Vector3 tangent = tan1[i];
|
||||||
|
|
||||||
// TODO: Review, not sure if tangent computation is right, just used reference proposed maths...
|
// Handle zero tangent (can happen with degenerate UVs)
|
||||||
#if defined(COMPUTE_TANGENTS_METHOD_01)
|
if (Vector3Length(tangent) < 0.0001f)
|
||||||
Vector3 tmp = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
|
{
|
||||||
tmp = Vector3Normalize(tmp);
|
// Create a tangent perpendicular to the normal
|
||||||
mesh->tangents[i*4 + 0] = tmp.x;
|
if (fabsf(normal.z) > 0.707f) tangent = (Vector3){ 1.0f, 0.0f, 0.0f };
|
||||||
mesh->tangents[i*4 + 1] = tmp.y;
|
else tangent = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
|
||||||
mesh->tangents[i*4 + 2] = tmp.z;
|
|
||||||
mesh->tangents[i*4 + 3] = 1.0f;
|
|
||||||
#else
|
|
||||||
Vector3OrthoNormalize(&normal, &tangent);
|
|
||||||
mesh->tangents[i*4 + 0] = tangent.x;
|
mesh->tangents[i*4 + 0] = tangent.x;
|
||||||
mesh->tangents[i*4 + 1] = tangent.y;
|
mesh->tangents[i*4 + 1] = tangent.y;
|
||||||
mesh->tangents[i*4 + 2] = tangent.z;
|
mesh->tangents[i*4 + 2] = tangent.z;
|
||||||
mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f)? -1.0f : 1.0f;
|
mesh->tangents[i*4 + 3] = 1.0f;
|
||||||
#endif
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gram-Schmidt orthogonalization to make tangent orthogonal to normal
|
||||||
|
// T_prime = T - N * dot(N, T)
|
||||||
|
Vector3 orthogonalized = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
|
||||||
|
|
||||||
|
// Handle cases where orthogonalized vector is too small
|
||||||
|
if (Vector3Length(orthogonalized) < 0.0001f)
|
||||||
|
{
|
||||||
|
// Create a tangent perpendicular to the normal
|
||||||
|
if (fabsf(normal.z) > 0.707f) orthogonalized = (Vector3){ 1.0f, 0.0f, 0.0f };
|
||||||
|
else orthogonalized = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Normalize the orthogonalized tangent
|
||||||
|
orthogonalized = Vector3Normalize(orthogonalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the calculated tangent
|
||||||
|
mesh->tangents[i*4 + 0] = orthogonalized.x;
|
||||||
|
mesh->tangents[i*4 + 1] = orthogonalized.y;
|
||||||
|
mesh->tangents[i*4 + 2] = orthogonalized.z;
|
||||||
|
|
||||||
|
// Calculate the handedness (w component)
|
||||||
|
mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, orthogonalized), tan2[i]) < 0.0f)? -1.0f : 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free temporary arrays
|
||||||
RL_FREE(tan1);
|
RL_FREE(tan1);
|
||||||
RL_FREE(tan2);
|
RL_FREE(tan2);
|
||||||
|
|
||||||
|
// Update vertex buffers if available
|
||||||
if (mesh->vboId != NULL)
|
if (mesh->vboId != NULL)
|
||||||
{
|
{
|
||||||
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
||||||
{
|
{
|
||||||
// Update existing vertex buffer
|
// Update existing tangent vertex buffer
|
||||||
rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
|
rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Load a new tangent attributes buffer
|
// Create new tangent vertex buffer
|
||||||
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
|
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up vertex attributes for shader
|
||||||
rlEnableVertexArray(mesh->vaoId);
|
rlEnableVertexArray(mesh->vaoId);
|
||||||
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);
|
||||||
@ -4577,13 +4642,13 @@ static Model LoadIQM(const char *fileName)
|
|||||||
//fileDataPtr += sizeof(IQMHeader); // Move file data pointer
|
//fileDataPtr += sizeof(IQMHeader); // Move file data pointer
|
||||||
|
|
||||||
// Meshes data processing
|
// Meshes data processing
|
||||||
imesh = RL_MALLOC(iqmHeader->num_meshes*sizeof(IQMMesh));
|
imesh = (IQMMesh *)RL_MALLOC(iqmHeader->num_meshes*sizeof(IQMMesh));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET);
|
||||||
//fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile);
|
//fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile);
|
||||||
memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh));
|
memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh));
|
||||||
|
|
||||||
model.meshCount = iqmHeader->num_meshes;
|
model.meshCount = iqmHeader->num_meshes;
|
||||||
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
|
|
||||||
model.materialCount = model.meshCount;
|
model.materialCount = model.meshCount;
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
@ -4611,24 +4676,24 @@ static Model LoadIQM(const char *fileName)
|
|||||||
|
|
||||||
model.meshes[i].vertexCount = imesh[i].num_vertexes;
|
model.meshes[i].vertexCount = imesh[i].num_vertexes;
|
||||||
|
|
||||||
model.meshes[i].vertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions
|
model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions
|
||||||
model.meshes[i].normals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals
|
model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals
|
||||||
model.meshes[i].texcoords = RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords
|
model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords
|
||||||
|
|
||||||
model.meshes[i].boneIds = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(unsigned char)); // Up-to 4 bones supported!
|
model.meshes[i].boneIds = (unsigned char *)RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(unsigned char)); // Up-to 4 bones supported!
|
||||||
model.meshes[i].boneWeights = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!
|
model.meshes[i].boneWeights = (float *)RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!
|
||||||
|
|
||||||
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
model.meshes[i].triangleCount = imesh[i].num_triangles;
|
||||||
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
model.meshes[i].indices = (unsigned short *)RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
|
||||||
|
|
||||||
// Animated vertex data, what we actually process for rendering
|
// Animated vertex data, what we actually process for rendering
|
||||||
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
||||||
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animVertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
model.meshes[i].animNormals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triangles data processing
|
// Triangles data processing
|
||||||
tri = RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle));
|
tri = (IQMTriangle *)RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET);
|
||||||
//fread(tri, sizeof(IQMTriangle), iqmHeader->num_triangles, iqmFile);
|
//fread(tri, sizeof(IQMTriangle), iqmHeader->num_triangles, iqmFile);
|
||||||
memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle));
|
memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle));
|
||||||
@ -4650,7 +4715,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vertex arrays data processing
|
// Vertex arrays data processing
|
||||||
va = RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
|
va = (IQMVertexArray *)RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET);
|
||||||
//fread(va, sizeof(IQMVertexArray), iqmHeader->num_vertexarrays, iqmFile);
|
//fread(va, sizeof(IQMVertexArray), iqmHeader->num_vertexarrays, iqmFile);
|
||||||
memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
|
memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));
|
||||||
@ -4661,7 +4726,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
{
|
{
|
||||||
case IQM_POSITION:
|
case IQM_POSITION:
|
||||||
{
|
{
|
||||||
vertex = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
|
vertex = (float *)RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
|
//fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
|
||||||
memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
|
memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
|
||||||
@ -4679,7 +4744,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
} break;
|
} break;
|
||||||
case IQM_NORMAL:
|
case IQM_NORMAL:
|
||||||
{
|
{
|
||||||
normal = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
|
normal = (float *)RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
|
//fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);
|
||||||
memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
|
memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));
|
||||||
@ -4697,7 +4762,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
} break;
|
} break;
|
||||||
case IQM_TEXCOORD:
|
case IQM_TEXCOORD:
|
||||||
{
|
{
|
||||||
text = RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float));
|
text = (float *)RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile);
|
//fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile);
|
||||||
memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float));
|
memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float));
|
||||||
@ -4714,7 +4779,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
} break;
|
} break;
|
||||||
case IQM_BLENDINDEXES:
|
case IQM_BLENDINDEXES:
|
||||||
{
|
{
|
||||||
blendi = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char));
|
blendi = (char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile);
|
//fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile);
|
||||||
memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char));
|
memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char));
|
||||||
@ -4731,7 +4796,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
} break;
|
} break;
|
||||||
case IQM_BLENDWEIGHTS:
|
case IQM_BLENDWEIGHTS:
|
||||||
{
|
{
|
||||||
blendw = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
blendw = (unsigned char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
|
//fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
|
||||||
memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
||||||
@ -4748,14 +4813,14 @@ static Model LoadIQM(const char *fileName)
|
|||||||
} break;
|
} break;
|
||||||
case IQM_COLOR:
|
case IQM_COLOR:
|
||||||
{
|
{
|
||||||
color = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
color = (unsigned char *)RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
||||||
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
//fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
//fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
|
//fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
|
||||||
memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));
|
||||||
|
|
||||||
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)
|
||||||
{
|
{
|
||||||
model.meshes[m].colors = RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char));
|
model.meshes[m].colors = (unsigned char *)RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
int vCounter = 0;
|
int vCounter = 0;
|
||||||
for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
|
for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
|
||||||
@ -4769,14 +4834,14 @@ static Model LoadIQM(const char *fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bones (joints) data processing
|
// Bones (joints) data processing
|
||||||
ijoint = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
|
ijoint = (IQMJoint *)RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET);
|
||||||
//fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);
|
//fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);
|
||||||
memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
|
memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
|
||||||
|
|
||||||
model.boneCount = iqmHeader->num_joints;
|
model.boneCount = iqmHeader->num_joints;
|
||||||
model.bones = RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo));
|
model.bones = (BoneInfo *)RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo));
|
||||||
model.bindPose = RL_MALLOC(iqmHeader->num_joints*sizeof(Transform));
|
model.bindPose = (Transform *)RL_MALLOC(iqmHeader->num_joints*sizeof(Transform));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < iqmHeader->num_joints; i++)
|
for (unsigned int i = 0; i < iqmHeader->num_joints; i++)
|
||||||
{
|
{
|
||||||
@ -4806,7 +4871,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
for (int i = 0; i < model.meshCount; i++)
|
for (int i = 0; i < model.meshCount; i++)
|
||||||
{
|
{
|
||||||
model.meshes[i].boneCount = model.boneCount;
|
model.meshes[i].boneCount = model.boneCount;
|
||||||
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
|
model.meshes[i].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
|
||||||
|
|
||||||
for (int j = 0; j < model.meshes[i].boneCount; j++)
|
for (int j = 0; j < model.meshes[i].boneCount; j++)
|
||||||
{
|
{
|
||||||
@ -4898,36 +4963,36 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get bones data
|
// Get bones data
|
||||||
IQMPose *poses = RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose));
|
IQMPose *poses = (IQMPose *)RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET);
|
||||||
//fread(poses, sizeof(IQMPose), iqmHeader->num_poses, iqmFile);
|
//fread(poses, sizeof(IQMPose), iqmHeader->num_poses, iqmFile);
|
||||||
memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose));
|
memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose));
|
||||||
|
|
||||||
// Get animations data
|
// Get animations data
|
||||||
*animCount = iqmHeader->num_anims;
|
*animCount = iqmHeader->num_anims;
|
||||||
IQMAnim *anim = RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim));
|
IQMAnim *anim = (IQMAnim *)RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET);
|
||||||
//fread(anim, sizeof(IQMAnim), iqmHeader->num_anims, iqmFile);
|
//fread(anim, sizeof(IQMAnim), iqmHeader->num_anims, iqmFile);
|
||||||
memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim));
|
memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim));
|
||||||
|
|
||||||
ModelAnimation *animations = RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation));
|
ModelAnimation *animations = (ModelAnimation *)RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation));
|
||||||
|
|
||||||
// frameposes
|
// frameposes
|
||||||
unsigned short *framedata = RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
|
unsigned short *framedata = (unsigned short *)RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
|
||||||
//fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET);
|
//fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET);
|
||||||
//fread(framedata, sizeof(unsigned short), iqmHeader->num_frames*iqmHeader->num_framechannels, iqmFile);
|
//fread(framedata, sizeof(unsigned short), iqmHeader->num_frames*iqmHeader->num_framechannels, iqmFile);
|
||||||
memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
|
memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
|
||||||
|
|
||||||
// joints
|
// joints
|
||||||
IQMJoint *joints = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
|
IQMJoint *joints = (IQMJoint *)RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
|
||||||
memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
|
memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
|
||||||
|
|
||||||
for (unsigned int a = 0; a < iqmHeader->num_anims; a++)
|
for (unsigned int a = 0; a < iqmHeader->num_anims; a++)
|
||||||
{
|
{
|
||||||
animations[a].frameCount = anim[a].num_frames;
|
animations[a].frameCount = anim[a].num_frames;
|
||||||
animations[a].boneCount = iqmHeader->num_poses;
|
animations[a].boneCount = iqmHeader->num_poses;
|
||||||
animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
|
animations[a].bones = (BoneInfo *)RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
|
||||||
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
|
animations[a].framePoses = (Transform **)RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
|
||||||
memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here
|
memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here
|
||||||
TraceLog(LOG_INFO, "IQM Anim %s", animations[a].name);
|
TraceLog(LOG_INFO, "IQM Anim %s", animations[a].name);
|
||||||
// animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
|
// animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
|
||||||
@ -4942,7 +5007,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
|
|||||||
animations[a].bones[j].parent = poses[j].parent;
|
animations[a].bones[j].parent = poses[j].parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqmHeader->num_poses*sizeof(Transform));
|
for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = (Transform *)RL_MALLOC(iqmHeader->num_poses*sizeof(Transform));
|
||||||
|
|
||||||
int dcounter = anim[a].first_frame*iqmHeader->num_framechannels;
|
int dcounter = anim[a].first_frame*iqmHeader->num_framechannels;
|
||||||
|
|
||||||
@ -5133,7 +5198,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||||||
}
|
}
|
||||||
else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer
|
else if ((cgltfImage->buffer_view != NULL) && (cgltfImage->buffer_view->buffer->data != NULL)) // Check if image is provided as data buffer
|
||||||
{
|
{
|
||||||
unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size);
|
unsigned char *data = (unsigned char *)RL_MALLOC(cgltfImage->buffer_view->size);
|
||||||
int offset = (int)cgltfImage->buffer_view->offset;
|
int offset = (int)cgltfImage->buffer_view->offset;
|
||||||
int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1;
|
int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1;
|
||||||
|
|
||||||
@ -5166,16 +5231,12 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||||||
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
|
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
|
||||||
{
|
{
|
||||||
*boneCount = (int)skin.joints_count;
|
*boneCount = (int)skin.joints_count;
|
||||||
BoneInfo *bones = RL_MALLOC(skin.joints_count*sizeof(BoneInfo));
|
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < skin.joints_count; i++)
|
for (unsigned int i = 0; i < skin.joints_count; i++)
|
||||||
{
|
{
|
||||||
cgltf_node node = *skin.joints[i];
|
cgltf_node node = *skin.joints[i];
|
||||||
if (node.name != NULL)
|
if (node.name != NULL) strncpy(bones[i].name, node.name, sizeof(bones[i].name) - 1);
|
||||||
{
|
|
||||||
strncpy(bones[i].name, node.name, sizeof(bones[i].name));
|
|
||||||
bones[i].name[sizeof(bones[i].name) - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find parent bone index
|
// Find parent bone index
|
||||||
int parentIndex = -1;
|
int parentIndex = -1;
|
||||||
@ -5201,7 +5262,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
/*********************************************************************************************
|
/*********************************************************************************************
|
||||||
|
|
||||||
Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend)
|
Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend)
|
||||||
Transform handling implemented by Paul Melis (@paulmelis).
|
Transform handling implemented by Paul Melis (@paulmelis)
|
||||||
Reviewed by Ramon Santamaria (@raysan5)
|
Reviewed by Ramon Santamaria (@raysan5)
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
@ -5211,10 +5272,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
PBR specular/glossiness flow and extended texture flows not supported
|
PBR specular/glossiness flow and extended texture flows not supported
|
||||||
- Supports multiple meshes per model (every primitives is loaded as a separate mesh)
|
- Supports multiple meshes per model (every primitives is loaded as a separate mesh)
|
||||||
- Supports basic animations
|
- Supports basic animations
|
||||||
- Transforms, including parent-child relations, are applied on the mesh data, but the
|
- Transforms, including parent-child relations, are applied on the mesh data,
|
||||||
hierarchy is not kept (as it can't be represented).
|
but the hierarchy is not kept (as it can't be represented)
|
||||||
- Mesh instances in the glTF file (i.e. same mesh linked from multiple nodes)
|
- Mesh instances in the glTF file (i.e. same mesh linked from multiple nodes)
|
||||||
are turned into separate raylib Meshes.
|
are turned into separate raylib Meshes
|
||||||
|
|
||||||
RESTRICTIONS:
|
RESTRICTIONS:
|
||||||
- Only triangle meshes supported
|
- Only triangle meshes supported
|
||||||
@ -5297,15 +5358,15 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
|
|
||||||
// Load our model data: meshes and materials
|
// Load our model data: meshes and materials
|
||||||
model.meshCount = primitivesCount;
|
model.meshCount = primitivesCount;
|
||||||
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
|
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
|
||||||
|
|
||||||
// NOTE: We keep an extra slot for default material, in case some mesh requires it
|
// NOTE: We keep an extra slot for default material, in case some mesh requires it
|
||||||
model.materialCount = (int)data->materials_count + 1;
|
model.materialCount = (int)data->materials_count + 1;
|
||||||
model.materials = RL_CALLOC(model.materialCount, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)
|
model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)
|
||||||
|
|
||||||
// Load mesh-material indices, by default all meshes are mapped to material index: 0
|
// Load mesh-material indices, by default all meshes are mapped to material index: 0
|
||||||
model.meshMaterial = RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
// Load materials data
|
// Load materials data
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@ -5430,7 +5491,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
// Any glTF mesh linked from more than one Node (i.e. instancing)
|
// Any glTF mesh linked from more than one Node (i.e. instancing)
|
||||||
// is turned into multiple Mesh's, as each Node will have its own
|
// is turned into multiple Mesh's, as each Node will have its own
|
||||||
// transform applied.
|
// transform applied.
|
||||||
// Note: the code below disregards the scenes defined in the file, all nodes are used.
|
// NOTE: The code below disregards the scenes defined in the file, all nodes are used.
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
int meshIndex = 0;
|
int meshIndex = 0;
|
||||||
for (unsigned int i = 0; i < data->nodes_count; i++)
|
for (unsigned int i = 0; i < data->nodes_count; i++)
|
||||||
@ -5475,7 +5536,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
{
|
{
|
||||||
// Init raylib mesh vertices to copy glTF attribute data
|
// Init raylib mesh vertices to copy glTF attribute data
|
||||||
model.meshes[meshIndex].vertexCount = (int)attribute->count;
|
model.meshes[meshIndex].vertexCount = (int)attribute->count;
|
||||||
model.meshes[meshIndex].vertices = RL_MALLOC(attribute->count*3*sizeof(float));
|
model.meshes[meshIndex].vertices = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
|
||||||
|
|
||||||
// Load 3 components of float data type into mesh.vertices
|
// Load 3 components of float data type into mesh.vertices
|
||||||
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)
|
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)
|
||||||
@ -5499,7 +5560,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
|
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
|
||||||
{
|
{
|
||||||
// Init raylib mesh normals to copy glTF attribute data
|
// Init raylib mesh normals to copy glTF attribute data
|
||||||
model.meshes[meshIndex].normals = RL_MALLOC(attribute->count*3*sizeof(float));
|
model.meshes[meshIndex].normals = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
|
||||||
|
|
||||||
// Load 3 components of float data type into mesh.normals
|
// Load 3 components of float data type into mesh.normals
|
||||||
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)
|
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)
|
||||||
@ -5516,14 +5577,14 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName);
|
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName);
|
||||||
}
|
}
|
||||||
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec3, float
|
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign
|
||||||
{
|
{
|
||||||
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
|
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
|
||||||
|
|
||||||
if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
|
if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
|
||||||
{
|
{
|
||||||
// Init raylib mesh tangent to copy glTF attribute data
|
// Init raylib mesh tangent to copy glTF attribute data
|
||||||
model.meshes[meshIndex].tangents = RL_MALLOC(attribute->count*4*sizeof(float));
|
model.meshes[meshIndex].tangents = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
|
||||||
|
|
||||||
// Load 4 components of float data type into mesh.tangents
|
// Load 4 components of float data type into mesh.tangents
|
||||||
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)
|
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)
|
||||||
@ -5532,10 +5593,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
float *tangents = model.meshes[meshIndex].tangents;
|
float *tangents = model.meshes[meshIndex].tangents;
|
||||||
for (unsigned int k = 0; k < attribute->count; k++)
|
for (unsigned int k = 0; k < attribute->count; k++)
|
||||||
{
|
{
|
||||||
Vector3 tt = Vector3Transform((Vector3){ tangents[3*k], tangents[3*k+1], tangents[3*k+2] }, worldMatrix);
|
Vector3 tt = Vector3Transform((Vector3){ tangents[4*k], tangents[4*k+1], tangents[4*k+2] }, worldMatrix);
|
||||||
tangents[3*k] = tt.x;
|
tangents[4*k] = tt.x;
|
||||||
tangents[3*k+1] = tt.y;
|
tangents[4*k+1] = tt.y;
|
||||||
tangents[3*k+2] = tt.z;
|
tangents[4*k+2] = tt.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName);
|
else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName);
|
||||||
@ -5609,10 +5670,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if (attribute->component_type == cgltf_component_type_r_8u)
|
if (attribute->component_type == cgltf_component_type_r_8u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned char *temp = RL_MALLOC(attribute->count*3*sizeof(unsigned char));
|
unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*3*sizeof(unsigned char));
|
||||||
LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);
|
LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes)
|
// Convert data to raylib color data type (4 bytes)
|
||||||
@ -5629,10 +5690,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_16u)
|
else if (attribute->component_type == cgltf_component_type_r_16u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned short *temp = RL_MALLOC(attribute->count*3*sizeof(unsigned short));
|
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*3*sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);
|
LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes)
|
// Convert data to raylib color data type (4 bytes)
|
||||||
@ -5649,10 +5710,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_32f)
|
else if (attribute->component_type == cgltf_component_type_r_32f)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
float *temp = RL_MALLOC(attribute->count*3*sizeof(float));
|
float *temp = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
|
||||||
LOAD_ATTRIBUTE(attribute, 3, float, temp);
|
LOAD_ATTRIBUTE(attribute, 3, float, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes)
|
// Convert data to raylib color data type (4 bytes)
|
||||||
@ -5673,7 +5734,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if (attribute->component_type == cgltf_component_type_r_8u)
|
if (attribute->component_type == cgltf_component_type_r_8u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load 4 components of unsigned char data type into mesh.colors
|
// Load 4 components of unsigned char data type into mesh.colors
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
|
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
|
||||||
@ -5681,10 +5742,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_16u)
|
else if (attribute->component_type == cgltf_component_type_r_16u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short));
|
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes)
|
// Convert data to raylib color data type (4 bytes)
|
||||||
@ -5695,10 +5756,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_32f)
|
else if (attribute->component_type == cgltf_component_type_r_32f)
|
||||||
{
|
{
|
||||||
// Init raylib mesh color to copy glTF attribute data
|
// Init raylib mesh color to copy glTF attribute data
|
||||||
model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
float *temp = RL_MALLOC(attribute->count*4*sizeof(float));
|
float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
|
||||||
LOAD_ATTRIBUTE(attribute, 4, float, temp);
|
LOAD_ATTRIBUTE(attribute, 4, float, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes), we expect the color data normalized
|
// Convert data to raylib color data type (4 bytes), we expect the color data normalized
|
||||||
@ -5724,7 +5785,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if (attribute->component_type == cgltf_component_type_r_16u)
|
if (attribute->component_type == cgltf_component_type_r_16u)
|
||||||
{
|
{
|
||||||
// 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 = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
|
||||||
|
|
||||||
// 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)
|
||||||
@ -5732,14 +5793,14 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_8u)
|
else if (attribute->component_type == cgltf_component_type_r_8u)
|
||||||
{
|
{
|
||||||
// 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 = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, 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 = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
|
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
|
||||||
|
|
||||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
|
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
|
||||||
@ -5783,7 +5844,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
{
|
{
|
||||||
cgltf_skin skin = data->skins[0];
|
cgltf_skin skin = data->skins[0];
|
||||||
model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
|
model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
|
||||||
model.bindPose = RL_MALLOC(model.boneCount*sizeof(Transform));
|
model.bindPose = (Transform *)RL_MALLOC(model.boneCount*sizeof(Transform));
|
||||||
|
|
||||||
for (int i = 0; i < model.boneCount; i++)
|
for (int i = 0; i < model.boneCount; i++)
|
||||||
{
|
{
|
||||||
@ -5815,15 +5876,17 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
|
|
||||||
for (unsigned int p = 0; p < mesh->primitives_count; p++)
|
for (unsigned int p = 0; p < mesh->primitives_count; p++)
|
||||||
{
|
{
|
||||||
|
bool hasJoints = false;
|
||||||
|
|
||||||
// NOTE: We only support primitives defined by triangles
|
// NOTE: We only support primitives defined by triangles
|
||||||
if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
|
if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
|
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
|
||||||
{
|
{
|
||||||
// NOTE: JOINTS_1 + WEIGHT_1 will be used for +4 joints influencing a vertex -> Not supported by raylib
|
// NOTE: JOINTS_1 + WEIGHT_1 will be used for +4 joints influencing a vertex -> Not supported by raylib
|
||||||
|
|
||||||
if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints) // JOINTS_n (vec4: 4 bones max per vertex / u8, u16)
|
if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints) // JOINTS_n (vec4: 4 bones max per vertex / u8, u16)
|
||||||
{
|
{
|
||||||
|
hasJoints = true;
|
||||||
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
|
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
|
||||||
|
|
||||||
// NOTE: JOINTS_n can only be vec4 and u8/u16
|
// NOTE: JOINTS_n can only be vec4 and u8/u16
|
||||||
@ -5838,7 +5901,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if (attribute->component_type == cgltf_component_type_r_8u)
|
if (attribute->component_type == cgltf_component_type_r_8u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh boneIds to copy glTF attribute data
|
// Init raylib mesh boneIds to copy glTF attribute data
|
||||||
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
|
model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
// Load attribute: vec4, u8 (unsigned char)
|
// Load attribute: vec4, u8 (unsigned char)
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)
|
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)
|
||||||
@ -5846,10 +5909,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_16u)
|
else if (attribute->component_type == cgltf_component_type_r_16u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh boneIds to copy glTF attribute data
|
// Init raylib mesh boneIds to copy glTF attribute data
|
||||||
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
|
model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned short *temp = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned short));
|
unsigned short *temp = (unsigned short *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
||||||
|
|
||||||
// Convert data to raylib color data type (4 bytes)
|
// Convert data to raylib color data type (4 bytes)
|
||||||
@ -5878,14 +5941,13 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
|
|
||||||
if (attribute->type == cgltf_type_vec4)
|
if (attribute->type == cgltf_type_vec4)
|
||||||
{
|
{
|
||||||
// TODO: Support component types: u8, u16?
|
|
||||||
if (attribute->component_type == cgltf_component_type_r_8u)
|
if (attribute->component_type == cgltf_component_type_r_8u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh bone weight to copy glTF attribute data
|
// Init raylib mesh bone weight to copy glTF attribute data
|
||||||
model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned char *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned char, temp);
|
LOAD_ATTRIBUTE(attribute, 4, unsigned char, temp);
|
||||||
|
|
||||||
// Convert data to raylib bone weight data type (4 bytes)
|
// Convert data to raylib bone weight data type (4 bytes)
|
||||||
@ -5896,10 +5958,10 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_16u)
|
else if (attribute->component_type == cgltf_component_type_r_16u)
|
||||||
{
|
{
|
||||||
// Init raylib mesh bone weight to copy glTF attribute data
|
// Init raylib mesh bone weight to copy glTF attribute data
|
||||||
model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
||||||
|
|
||||||
// Load data into a temp buffer to be converted to raylib data type
|
// Load data into a temp buffer to be converted to raylib data type
|
||||||
unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short));
|
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
|
||||||
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
|
||||||
|
|
||||||
// Convert data to raylib bone weight data type
|
// Convert data to raylib bone weight data type
|
||||||
@ -5910,10 +5972,11 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
else if (attribute->component_type == cgltf_component_type_r_32f)
|
else if (attribute->component_type == cgltf_component_type_r_32f)
|
||||||
{
|
{
|
||||||
// Init raylib mesh bone weight to copy glTF attribute data
|
// Init raylib mesh bone weight to copy glTF attribute data
|
||||||
model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
||||||
|
|
||||||
// Load 4 components of float data type into mesh.boneWeights
|
// Load 4 components of float data type into mesh.boneWeights
|
||||||
// for cgltf_attribute_type_weights we have:
|
// for cgltf_attribute_type_weights we have:
|
||||||
|
|
||||||
// - data.meshes[0] (256 vertices)
|
// - data.meshes[0] (256 vertices)
|
||||||
// - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)
|
// - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)
|
||||||
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)
|
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)
|
||||||
@ -5924,10 +5987,37 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if we are animated, and the mesh was not given any bone assignments, but is the child of a bone node
|
||||||
|
// in this case we need to fully attach all the verts to the parent bone so it will animate with the bone
|
||||||
|
if (data->skins_count > 0 && !hasJoints && node->parent != NULL && node->parent->mesh == NULL)
|
||||||
|
{
|
||||||
|
int parentBoneId = -1;
|
||||||
|
for (int joint = 0; joint < model.boneCount; joint++)
|
||||||
|
{
|
||||||
|
if (data->skins[0].joints[joint] == node->parent)
|
||||||
|
{
|
||||||
|
parentBoneId = joint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentBoneId >= 0)
|
||||||
|
{
|
||||||
|
model.meshes[meshIndex].boneIds = (unsigned char *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
|
||||||
|
model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
|
||||||
|
|
||||||
|
for (int vertexIndex = 0; vertexIndex < model.meshes[meshIndex].vertexCount*4; vertexIndex += 4)
|
||||||
|
{
|
||||||
|
model.meshes[meshIndex].boneIds[vertexIndex] = (unsigned char)parentBoneId;
|
||||||
|
model.meshes[meshIndex].boneWeights[vertexIndex] = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Animated vertex data
|
// Animated vertex data
|
||||||
model.meshes[meshIndex].animVertices = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
model.meshes[meshIndex].animVertices = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
||||||
memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));
|
||||||
model.meshes[meshIndex].animNormals = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
model.meshes[meshIndex].animNormals = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));
|
||||||
if (model.meshes[meshIndex].normals != NULL)
|
if (model.meshes[meshIndex].normals != NULL)
|
||||||
{
|
{
|
||||||
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));
|
||||||
@ -5935,7 +6025,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
|
|
||||||
// Bone Transform Matrices
|
// Bone Transform Matrices
|
||||||
model.meshes[meshIndex].boneCount = model.boneCount;
|
model.meshes[meshIndex].boneCount = model.boneCount;
|
||||||
model.meshes[meshIndex].boneMatrices = RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
|
model.meshes[meshIndex].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[meshIndex].boneCount, sizeof(Matrix));
|
||||||
|
|
||||||
for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
|
for (int j = 0; j < model.meshes[meshIndex].boneCount; j++)
|
||||||
{
|
{
|
||||||
@ -5944,7 +6034,6 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
|
|
||||||
meshIndex++; // Move to next mesh
|
meshIndex++; // Move to next mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free all cgltf loaded data
|
// Free all cgltf loaded data
|
||||||
@ -6126,7 +6215,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||||||
{
|
{
|
||||||
cgltf_skin skin = data->skins[0];
|
cgltf_skin skin = data->skins[0];
|
||||||
*animCount = (int)data->animations_count;
|
*animCount = (int)data->animations_count;
|
||||||
animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
|
animations = (ModelAnimation *)RL_CALLOC(data->animations_count, sizeof(ModelAnimation));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < data->animations_count; i++)
|
for (unsigned int i = 0; i < data->animations_count; i++)
|
||||||
{
|
{
|
||||||
@ -6141,7 +6230,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||||||
cgltf_interpolation_type interpolationType;
|
cgltf_interpolation_type interpolationType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Channels *boneChannels = RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));
|
struct Channels *boneChannels = (struct Channels *)RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));
|
||||||
float animDuration = 0.0f;
|
float animDuration = 0.0f;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < animData.channels_count; j++)
|
for (unsigned int j = 0; j < animData.channels_count; j++)
|
||||||
@ -6199,18 +6288,14 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||||||
animDuration = (t > animDuration)? t : animDuration;
|
animDuration = (t > animDuration)? t : animDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animData.name != NULL)
|
if (animData.name != NULL) strncpy(animations[i].name, animData.name, sizeof(animations[i].name) - 1);
|
||||||
{
|
|
||||||
strncpy(animations[i].name, animData.name, sizeof(animations[i].name));
|
|
||||||
animations[i].name[sizeof(animations[i].name) - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY) + 1;
|
animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY) + 1;
|
||||||
animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
|
animations[i].framePoses = (Transform **)RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
|
||||||
|
|
||||||
for (int j = 0; j < animations[i].frameCount; j++)
|
for (int j = 0; j < animations[i].frameCount; j++)
|
||||||
{
|
{
|
||||||
animations[i].framePoses[j] = RL_MALLOC(animations[i].boneCount*sizeof(Transform));
|
animations[i].framePoses[j] = (Transform *)RL_MALLOC(animations[i].boneCount*sizeof(Transform));
|
||||||
float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;
|
float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;
|
||||||
|
|
||||||
for (int k = 0; k < animations[i].boneCount; k++)
|
for (int k = 0; k < animations[i].boneCount; k++)
|
||||||
@ -6360,7 +6445,7 @@ static Model LoadVOX(const char *fileName)
|
|||||||
|
|
||||||
// Copy colors
|
// Copy colors
|
||||||
size = pmesh->vertexCount*sizeof(Color);
|
size = pmesh->vertexCount*sizeof(Color);
|
||||||
pmesh->colors = RL_MALLOC(size);
|
pmesh->colors = (unsigned char *)RL_MALLOC(size);
|
||||||
memcpy(pmesh->colors, pcolors, size);
|
memcpy(pmesh->colors, pcolors, size);
|
||||||
|
|
||||||
// First material index
|
// First material index
|
||||||
@ -6496,7 +6581,7 @@ static Model LoadM3D(const char *fileName)
|
|||||||
|
|
||||||
// If no map is provided, or we have colors defined, we allocate storage for vertex colors
|
// If no map is provided, or we have colors defined, we allocate storage for vertex colors
|
||||||
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
|
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
|
||||||
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
|
||||||
|
|
||||||
// If no map is provided and we allocated vertex colors, set them to white
|
// If no map is provided and we allocated vertex colors, set them to white
|
||||||
if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))
|
if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))
|
||||||
@ -6530,11 +6615,11 @@ static Model LoadM3D(const char *fileName)
|
|||||||
// Without vertex color (full transparency), we use the default color
|
// Without vertex color (full transparency), we use the default color
|
||||||
if (model.meshes[k].colors != NULL)
|
if (model.meshes[k].colors != NULL)
|
||||||
{
|
{
|
||||||
if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)
|
if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xff000000)
|
||||||
memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);
|
memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);
|
||||||
if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xFF000000)
|
if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xff000000)
|
||||||
memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);
|
memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);
|
||||||
if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xFF000000)
|
if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xff000000)
|
||||||
memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);
|
memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6663,13 +6748,13 @@ static Model LoadM3D(const char *fileName)
|
|||||||
if (m3d->numbone)
|
if (m3d->numbone)
|
||||||
{
|
{
|
||||||
model.boneCount = m3d->numbone + 1;
|
model.boneCount = m3d->numbone + 1;
|
||||||
model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));
|
model.bones = (BoneInfo *)RL_CALLOC(model.boneCount, sizeof(BoneInfo));
|
||||||
model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));
|
model.bindPose = (Transform *)RL_CALLOC(model.boneCount, sizeof(Transform));
|
||||||
|
|
||||||
for (i = 0; i < (int)m3d->numbone; i++)
|
for (i = 0; i < (int)m3d->numbone; i++)
|
||||||
{
|
{
|
||||||
model.bones[i].parent = m3d->bone[i].parent;
|
model.bones[i].parent = m3d->bone[i].parent;
|
||||||
strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name));
|
strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name) - 1);
|
||||||
model.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;
|
model.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;
|
||||||
model.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;
|
model.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;
|
||||||
model.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;
|
model.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;
|
||||||
@ -6715,7 +6800,7 @@ static Model LoadM3D(const char *fileName)
|
|||||||
memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
|
memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));
|
||||||
|
|
||||||
model.meshes[i].boneCount = model.boneCount;
|
model.meshes[i].boneCount = model.boneCount;
|
||||||
model.meshes[i].boneMatrices = RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
|
model.meshes[i].boneMatrices = (Matrix *)RL_CALLOC(model.meshes[i].boneCount, sizeof(Matrix));
|
||||||
for (j = 0; j < model.meshes[i].boneCount; j++)
|
for (j = 0; j < model.meshes[i].boneCount; j++)
|
||||||
{
|
{
|
||||||
model.meshes[i].boneMatrices[j] = MatrixIdentity();
|
model.meshes[i].boneMatrices[j] = MatrixIdentity();
|
||||||
@ -6765,24 +6850,23 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
animations = RL_MALLOC(m3d->numaction*sizeof(ModelAnimation));
|
animations = (ModelAnimation *)RL_CALLOC(m3d->numaction, sizeof(ModelAnimation));
|
||||||
*animCount = m3d->numaction;
|
*animCount = m3d->numaction;
|
||||||
|
|
||||||
for (unsigned int a = 0; a < m3d->numaction; a++)
|
for (unsigned int a = 0; a < m3d->numaction; a++)
|
||||||
{
|
{
|
||||||
animations[a].frameCount = m3d->action[a].durationmsec/M3D_ANIMDELAY;
|
animations[a].frameCount = m3d->action[a].durationmsec/M3D_ANIMDELAY;
|
||||||
animations[a].boneCount = m3d->numbone + 1;
|
animations[a].boneCount = m3d->numbone + 1;
|
||||||
animations[a].bones = RL_MALLOC((m3d->numbone + 1)*sizeof(BoneInfo));
|
animations[a].bones = (BoneInfo *)RL_MALLOC((m3d->numbone + 1)*sizeof(BoneInfo));
|
||||||
animations[a].framePoses = RL_MALLOC(animations[a].frameCount*sizeof(Transform *));
|
animations[a].framePoses = (Transform **)RL_MALLOC(animations[a].frameCount*sizeof(Transform *));
|
||||||
strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name));
|
strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name) - 1);
|
||||||
animations[a].name[sizeof(animations[a].name) - 1] = '\0';
|
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "MODEL: [%s] animation #%i: %i msec, %i frames", fileName, a, m3d->action[a].durationmsec, animations[a].frameCount);
|
TRACELOG(LOG_INFO, "MODEL: [%s] animation #%i: %i msec, %i frames", fileName, a, m3d->action[a].durationmsec, animations[a].frameCount);
|
||||||
|
|
||||||
for (i = 0; i < (int)m3d->numbone; i++)
|
for (i = 0; i < (int)m3d->numbone; i++)
|
||||||
{
|
{
|
||||||
animations[a].bones[i].parent = m3d->bone[i].parent;
|
animations[a].bones[i].parent = m3d->bone[i].parent;
|
||||||
strncpy(animations[a].bones[i].name, m3d->bone[i].name, sizeof(animations[a].bones[i].name));
|
strncpy(animations[a].bones[i].name, m3d->bone[i].name, sizeof(animations[a].bones[i].name) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A special, never transformed "no bone" bone, used for boneless vertices
|
// A special, never transformed "no bone" bone, used for boneless vertices
|
||||||
@ -6793,7 +6877,7 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou
|
|||||||
// regular intervals, so let the M3D SDK do the heavy lifting and calculate interpolated bones
|
// regular intervals, so let the M3D SDK do the heavy lifting and calculate interpolated bones
|
||||||
for (i = 0; i < animations[a].frameCount; i++)
|
for (i = 0; i < animations[a].frameCount; i++)
|
||||||
{
|
{
|
||||||
animations[a].framePoses[i] = RL_MALLOC((m3d->numbone + 1)*sizeof(Transform));
|
animations[a].framePoses[i] = (Transform *)RL_MALLOC((m3d->numbone + 1)*sizeof(Transform));
|
||||||
|
|
||||||
m3db_t *pose = m3d_pose(m3d, a, i*M3D_ANIMDELAY);
|
m3db_t *pose = m3d_pose(m3d, a, i*M3D_ANIMDELAY);
|
||||||
|
|
||||||
|
@ -470,27 +470,39 @@ void DrawCircleLinesV(Vector2 center, float radius, Color color)
|
|||||||
|
|
||||||
// Draw ellipse
|
// Draw ellipse
|
||||||
void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
||||||
|
{
|
||||||
|
DrawEllipseV((Vector2){ (float)centerX, (float)centerY }, radiusH, radiusV, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw ellipse (Vector version)
|
||||||
|
void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color)
|
||||||
{
|
{
|
||||||
rlBegin(RL_TRIANGLES);
|
rlBegin(RL_TRIANGLES);
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radiusH, (float)centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radiusH, center.y + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radiusH, (float)centerY + sinf(DEG2RAD*i)*radiusV);
|
rlVertex2f(center.x + cosf(DEG2RAD*i)*radiusH, center.y + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw ellipse outline
|
// Draw ellipse outline
|
||||||
void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
||||||
|
{
|
||||||
|
DrawEllipseLinesV((Vector2){ (float)centerX, (float)centerY }, radiusH, radiusV, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw ellipse outline
|
||||||
|
void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color)
|
||||||
{
|
{
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radiusH, centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radiusH, center.y + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f(centerX + cosf(DEG2RAD*i)*radiusH, centerY + sinf(DEG2RAD*i)*radiusV);
|
rlVertex2f(center.x + cosf(DEG2RAD*i)*radiusH, center.y + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
@ -774,7 +786,7 @@ void DrawRectangleGradientH(int posX, int posY, int width, int height, Color lef
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a gradient-filled rectangle
|
// Draw a gradient-filled rectangle
|
||||||
void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
|
void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight)
|
||||||
{
|
{
|
||||||
rlSetTexture(GetShapesTexture().id);
|
rlSetTexture(GetShapesTexture().id);
|
||||||
Rectangle shapeRect = GetShapesTextureRectangle();
|
Rectangle shapeRect = GetShapesTextureRectangle();
|
||||||
@ -791,11 +803,11 @@ void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Col
|
|||||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||||
rlVertex2f(rec.x, rec.y + rec.height);
|
rlVertex2f(rec.x, rec.y + rec.height);
|
||||||
|
|
||||||
rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
|
rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
|
||||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||||
|
|
||||||
rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
|
rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
|
||||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||||
rlVertex2f(rec.x + rec.width, rec.y);
|
rlVertex2f(rec.x + rec.width, rec.y);
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
28
src/rtext.c
28
src/rtext.c
@ -161,6 +161,10 @@ extern void LoadFontDefault(void)
|
|||||||
{
|
{
|
||||||
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
||||||
|
|
||||||
|
// check to see if we have allready allocated the font for an image, and if we don't need to upload, then just return
|
||||||
|
if (defaultFont.glyphs != NULL && !isGpuReady)
|
||||||
|
return;
|
||||||
|
|
||||||
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||||
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||||
|
|
||||||
@ -249,7 +253,7 @@ extern void LoadFontDefault(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short)] = 0xFF;
|
((unsigned char *)imFont.data)[(i + j)*sizeof(short)] = 0xff;
|
||||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short) + 1] = 0x00;
|
((unsigned char *)imFont.data)[(i + j)*sizeof(short) + 1] = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +261,18 @@ extern void LoadFontDefault(void)
|
|||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGpuReady) defaultFont.texture = LoadTextureFromImage(imFont);
|
if (isGpuReady)
|
||||||
|
{
|
||||||
|
defaultFont.texture = LoadTextureFromImage(imFont);
|
||||||
|
|
||||||
|
// we have already loaded the font glyph data an image, and the GPU is ready, we are done
|
||||||
|
// if we don't do this, we will leak memory by reallocating the glyphs and rects
|
||||||
|
if (defaultFont.glyphs != NULL)
|
||||||
|
{
|
||||||
|
UnloadImage(imFont);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
|
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -282,7 +297,7 @@ extern void LoadFontDefault(void)
|
|||||||
|
|
||||||
testPosX += (int)(defaultFont.recs[i].width + (float)charsDivisor);
|
testPosX += (int)(defaultFont.recs[i].width + (float)charsDivisor);
|
||||||
|
|
||||||
if (testPosX >= defaultFont.texture.width)
|
if (testPosX >= imFont.width)
|
||||||
{
|
{
|
||||||
currentLine++;
|
currentLine++;
|
||||||
currentPosX = 2*charsDivisor + charsWidth[i];
|
currentPosX = 2*charsDivisor + charsWidth[i];
|
||||||
@ -316,6 +331,9 @@ extern void UnloadFontDefault(void)
|
|||||||
if (isGpuReady) UnloadTexture(defaultFont.texture);
|
if (isGpuReady) UnloadTexture(defaultFont.texture);
|
||||||
RL_FREE(defaultFont.glyphs);
|
RL_FREE(defaultFont.glyphs);
|
||||||
RL_FREE(defaultFont.recs);
|
RL_FREE(defaultFont.recs);
|
||||||
|
defaultFont.glyphCount = 0;
|
||||||
|
defaultFont.glyphs = NULL;
|
||||||
|
defaultFont.recs = NULL;
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_DEFAULT_FONT
|
#endif // SUPPORT_DEFAULT_FONT
|
||||||
|
|
||||||
@ -373,7 +391,7 @@ Font LoadFont(const char *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.baseSize, font.glyphCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1560,7 +1578,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace text string
|
// Replace text string
|
||||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy()
|
// REQUIRES: strstr(), strncpy(), strcpy()
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *TextReplace(const char *text, const char *replace, const char *by)
|
char *TextReplace(const char *text, const char *replace, const char *by)
|
||||||
{
|
{
|
||||||
|
106
src/rtextures.c
106
src/rtextures.c
@ -832,10 +832,11 @@ Image GenImageGradientLinear(int width, int height, int direction, Color start,
|
|||||||
|
|
||||||
// Calculate how far the top-left pixel is along the gradient direction from the center of said gradient
|
// Calculate how far the top-left pixel is along the gradient direction from the center of said gradient
|
||||||
float startingPos = 0.5f - (cosDir*width/2) - (sinDir*height/2);
|
float startingPos = 0.5f - (cosDir*width/2) - (sinDir*height/2);
|
||||||
|
|
||||||
// With directions that lie in the first or third quadrant (i.e. from top-left to
|
// With directions that lie in the first or third quadrant (i.e. from top-left to
|
||||||
// bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient
|
// bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient
|
||||||
// (i.e. the pixel which should become one of the gradient's ends color); while for
|
// (i.e. the pixel which should become one of the gradient's ends color); while for
|
||||||
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0).
|
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0)
|
||||||
float maxPosValue = ((signbit(sinDir) != 0) == (signbit(cosDir) != 0))? fabsf(startingPos) : fabsf(startingPos + width*cosDir);
|
float maxPosValue = ((signbit(sinDir) != 0) == (signbit(cosDir) != 0))? fabsf(startingPos) : fabsf(startingPos + width*cosDir);
|
||||||
for (int i = 0; i < width; i++)
|
for (int i = 0; i < width; i++)
|
||||||
{
|
{
|
||||||
@ -2101,8 +2102,8 @@ void ImageBlurGaussian(Image *image, int blurSize)
|
|||||||
Color *pixels = LoadImageColors(*image);
|
Color *pixels = LoadImageColors(*image);
|
||||||
|
|
||||||
// Loop switches between pixelsCopy1 and pixelsCopy2
|
// Loop switches between pixelsCopy1 and pixelsCopy2
|
||||||
Vector4 *pixelsCopy1 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
Vector4 *pixelsCopy1 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||||
Vector4 *pixelsCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
Vector4 *pixelsCopy2 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||||
|
|
||||||
for (int i = 0; i < (image->height*image->width); i++)
|
for (int i = 0; i < (image->height*image->width); i++)
|
||||||
{
|
{
|
||||||
@ -2216,9 +2217,9 @@ void ImageBlurGaussian(Image *image, int blurSize)
|
|||||||
else if (pixelsCopy1[i].w <= 255.0f)
|
else if (pixelsCopy1[i].w <= 255.0f)
|
||||||
{
|
{
|
||||||
float alpha = (float)pixelsCopy1[i].w/255.0f;
|
float alpha = (float)pixelsCopy1[i].w/255.0f;
|
||||||
pixels[i].r = (unsigned char)((float)pixelsCopy1[i].x/alpha);
|
pixels[i].r = (unsigned char)fminf((float)pixelsCopy1[i].x/alpha, 255.0);
|
||||||
pixels[i].g = (unsigned char)((float)pixelsCopy1[i].y/alpha);
|
pixels[i].g = (unsigned char)fminf((float)pixelsCopy1[i].y/alpha, 255.0);
|
||||||
pixels[i].b = (unsigned char)((float)pixelsCopy1[i].z/alpha);
|
pixels[i].b = (unsigned char)fminf((float)pixelsCopy1[i].z/alpha, 255.0);
|
||||||
pixels[i].a = (unsigned char) pixelsCopy1[i].w;
|
pixels[i].a = (unsigned char) pixelsCopy1[i].w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2250,8 +2251,8 @@ void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize)
|
|||||||
|
|
||||||
Color *pixels = LoadImageColors(*image);
|
Color *pixels = LoadImageColors(*image);
|
||||||
|
|
||||||
Vector4 *imageCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
Vector4 *imageCopy2 = (Vector4 *)RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
|
||||||
Vector4 *temp = RL_MALLOC(kernelSize*sizeof(Vector4));
|
Vector4 *temp = (Vector4 *)RL_MALLOC(kernelSize*sizeof(Vector4));
|
||||||
|
|
||||||
for (int i = 0; i < kernelSize; i++)
|
for (int i = 0; i < kernelSize; i++)
|
||||||
{
|
{
|
||||||
@ -2926,7 +2927,16 @@ void ImageColorReplace(Image *image, Color color, Color replace)
|
|||||||
image->data = pixels;
|
image->data = pixels;
|
||||||
image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
|
||||||
ImageFormat(image, format);
|
// Only convert back to original format if it supported alpha
|
||||||
|
if ((format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) ||
|
||||||
|
(format == PIXELFORMAT_UNCOMPRESSED_R5G6B5) ||
|
||||||
|
(format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ||
|
||||||
|
(format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) ||
|
||||||
|
(format == PIXELFORMAT_UNCOMPRESSED_R16G16B16) ||
|
||||||
|
(format == PIXELFORMAT_COMPRESSED_DXT1_RGB) ||
|
||||||
|
(format == PIXELFORMAT_COMPRESSED_ETC1_RGB) ||
|
||||||
|
(format == PIXELFORMAT_COMPRESSED_ETC2_RGB) ||
|
||||||
|
(format == PIXELFORMAT_COMPRESSED_PVRT_RGB)) ImageFormat(image, format);
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_IMAGE_MANIPULATION
|
#endif // SUPPORT_IMAGE_MANIPULATION
|
||||||
|
|
||||||
@ -3564,34 +3574,43 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co
|
|||||||
int dx = x2 - x1;
|
int dx = x2 - x1;
|
||||||
int dy = y2 - y1;
|
int dy = y2 - y1;
|
||||||
|
|
||||||
// Draw the main line between (x1, y1) and (x2, y2)
|
|
||||||
ImageDrawLine(dst, x1, y1, x2, y2, color);
|
|
||||||
|
|
||||||
// Determine if the line is more horizontal or vertical
|
// Determine if the line is more horizontal or vertical
|
||||||
if ((dx != 0) && (abs(dy/dx) < 1))
|
if ((dx != 0) && (abs(dy/dx) < 1))
|
||||||
{
|
{
|
||||||
// Line is more horizontal
|
// Line is more horizontal
|
||||||
// Calculate half the width of the line
|
|
||||||
int wy = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dx));
|
|
||||||
|
|
||||||
// Draw additional lines above and below the main line
|
// How many additional lines to draw
|
||||||
for (int i = 1; i <= wy; i++)
|
int wy = thick - 1;
|
||||||
|
|
||||||
|
// Draw the main line and lower half
|
||||||
|
for (int i = 0; i <= ((wy+1)/2); i++)
|
||||||
{
|
{
|
||||||
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color); // Draw above the main line
|
ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color);
|
||||||
ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color); // Draw below the main line
|
}
|
||||||
|
|
||||||
|
// Draw the upper half
|
||||||
|
for (int i = 1; i <= (wy/2); i++)
|
||||||
|
{
|
||||||
|
ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dy != 0)
|
else if (dy != 0)
|
||||||
{
|
{
|
||||||
// Line is more vertical or perfectly horizontal
|
// Line is more vertical or perfectly horizontal
|
||||||
// Calculate half the width of the line
|
|
||||||
int wx = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dy));
|
|
||||||
|
|
||||||
// Draw additional lines to the left and right of the main line
|
// How many additional lines to draw
|
||||||
for (int i = 1; i <= wx; i++)
|
int wx = thick - 1;
|
||||||
|
|
||||||
|
//Draw the main line and right half
|
||||||
|
for (int i = 0; i <= ((wx+1)/2); i++)
|
||||||
{
|
{
|
||||||
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color); // Draw left of the main line
|
ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color);
|
||||||
ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color); // Draw right of the main line
|
}
|
||||||
|
|
||||||
|
// Draw the left half
|
||||||
|
for (int i = 1; i <= (wx/2); i++)
|
||||||
|
{
|
||||||
|
ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3835,7 +3854,7 @@ void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c
|
|||||||
|
|
||||||
// Calculate the inverse of the sum of the barycentric coordinates for normalization
|
// Calculate the inverse of the sum of the barycentric coordinates for normalization
|
||||||
// NOTE 1: Here, we act as if we multiply by 255 the reciprocal, which avoids additional
|
// NOTE 1: Here, we act as if we multiply by 255 the reciprocal, which avoids additional
|
||||||
// calculations in the loop. This is acceptable because we are only interpolating colors.
|
// calculations in the loop. This is acceptable because we are only interpolating colors
|
||||||
// NOTE 2: This sum remains constant throughout the triangle
|
// NOTE 2: This sum remains constant throughout the triangle
|
||||||
float wInvSum = 255.0f/(w1Row + w2Row + w3Row);
|
float wInvSum = 255.0f/(w1Row + w2Row + w3Row);
|
||||||
|
|
||||||
@ -3890,7 +3909,7 @@ void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a triangle fan defined by points within an image (first vertex is the center)
|
// Draw a triangle fan defined by points within an image (first vertex is the center)
|
||||||
void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color)
|
void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointCount >= 3)
|
if (pointCount >= 3)
|
||||||
{
|
{
|
||||||
@ -3902,7 +3921,7 @@ void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color col
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a triangle strip defined by points within an image
|
// Draw a triangle strip defined by points within an image
|
||||||
void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color)
|
void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color)
|
||||||
{
|
{
|
||||||
if (pointCount >= 3)
|
if (pointCount >= 3)
|
||||||
{
|
{
|
||||||
@ -4337,14 +4356,17 @@ void UnloadRenderTexture(RenderTexture2D target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update GPU texture with new data
|
// Update GPU texture with new data
|
||||||
// NOTE: pixels data must match texture.format
|
// NOTE 1: pixels data must match texture.format
|
||||||
|
// NOTE 2: pixels data must contain at least as many pixels as texture
|
||||||
void UpdateTexture(Texture2D texture, const void *pixels)
|
void UpdateTexture(Texture2D texture, const void *pixels)
|
||||||
{
|
{
|
||||||
rlUpdateTexture(texture.id, 0, 0, texture.width, texture.height, texture.format, pixels);
|
rlUpdateTexture(texture.id, 0, 0, texture.width, texture.height, texture.format, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update GPU texture rectangle with new data
|
// Update GPU texture rectangle with new data
|
||||||
// NOTE: pixels data must match texture.format
|
// NOTE 1: pixels data must match texture.format
|
||||||
|
// NOTE 2: pixels data must contain as many pixels as rec contains
|
||||||
|
// NOTE 3: rec must fit completely within texture's width and height
|
||||||
void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels)
|
void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels)
|
||||||
{
|
{
|
||||||
rlUpdateTexture(texture.id, (int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, texture.format, pixels);
|
rlUpdateTexture(texture.id, (int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, texture.format, pixels);
|
||||||
@ -5147,10 +5169,10 @@ Color GetColor(unsigned int hexValue)
|
|||||||
{
|
{
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
color.r = (unsigned char)(hexValue >> 24) & 0xFF;
|
color.r = (unsigned char)(hexValue >> 24) & 0xff;
|
||||||
color.g = (unsigned char)(hexValue >> 16) & 0xFF;
|
color.g = (unsigned char)(hexValue >> 16) & 0xff;
|
||||||
color.b = (unsigned char)(hexValue >> 8) & 0xFF;
|
color.b = (unsigned char)(hexValue >> 8) & 0xff;
|
||||||
color.a = (unsigned char)hexValue & 0xFF;
|
color.a = (unsigned char)hexValue & 0xff;
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
@ -5390,17 +5412,16 @@ static float HalfToFloat(unsigned short x)
|
|||||||
{
|
{
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
float fm;
|
float fm;
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
} uni;
|
} uni;
|
||||||
|
|
||||||
const unsigned int e = (x & 0x7C00) >> 10; // Exponent
|
const unsigned int e = (x & 0x7c00) >> 10; // Exponent
|
||||||
const unsigned int m = (x & 0x03FF) << 13; // Mantissa
|
const unsigned int m = (x & 0x03ff) << 13; // Mantissa
|
||||||
uni.fm = (float)m;
|
uni.fm = (float)m;
|
||||||
const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
const unsigned int v = uni.ui >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
||||||
uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
|
uni.ui = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007fe000)); // sign : normalized : denormalized
|
||||||
|
|
||||||
result = uni.fm;
|
result = uni.fm;
|
||||||
|
|
||||||
@ -5412,18 +5433,17 @@ static unsigned short FloatToHalf(float x)
|
|||||||
{
|
{
|
||||||
unsigned short result = 0;
|
unsigned short result = 0;
|
||||||
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
float fm;
|
float fm;
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
} uni;
|
} uni;
|
||||||
uni.fm = x;
|
uni.fm = x;
|
||||||
|
|
||||||
const unsigned int b = uni.ui + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
const unsigned int b = uni.ui + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
||||||
const unsigned int e = (b & 0x7F800000) >> 23; // Exponent
|
const unsigned int e = (b & 0x7f800000) >> 23; // Exponent
|
||||||
const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
const unsigned int m = b & 0x007fffff; // Mantissa; in line below: 0x007ff000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||||
|
|
||||||
result = (b & 0x80000000) >> 16 | (e > 112)*((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))*((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143)*0x7FFF; // sign : normalized : denormalized : saturate
|
result = (b & 0x80000000) >> 16 | (e > 112)*((((e - 112) << 10) & 0x7c00) | m >> 13) | ((e < 113) & (e > 101))*((((0x007ff000 + m) >> (125 - e)) + 1) >> 1) | (e > 143)*0x7fff; // sign : normalized : denormalized : saturate
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ void UnloadFileText(char *text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save text data to file (write), string must be '\0' terminated
|
// Save text data to file (write), string must be '\0' terminated
|
||||||
bool SaveFileText(const char *fileName, char *text)
|
bool SaveFileText(const char *fileName, const char *text)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user