Merge branch 'raysan5:master' into Add-RL_POINTS
This commit is contained in:
commit
fb853ea03c
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -118,14 +118,15 @@ GTAGS
|
||||||
# Zig programming language
|
# Zig programming language
|
||||||
.zig-cache/
|
.zig-cache/
|
||||||
zig-cache/
|
zig-cache/
|
||||||
|
zig-pkg/
|
||||||
zig-out/
|
zig-out/
|
||||||
build/
|
build/
|
||||||
build-*/
|
build-*/
|
||||||
docgen_tmp/
|
docgen_tmp/
|
||||||
|
|
||||||
# Tools stuff
|
# Tools stuff
|
||||||
tools/parser/rlparser.exe
|
tools/rlparser/rlparser.exe
|
||||||
tools/parser/rlparser
|
tools/rlparser/rlparser
|
||||||
tools/rexm/rexm.exe
|
tools/rexm/rexm.exe
|
||||||
tools/rexm/rexm
|
tools/rexm/rexm
|
||||||
|
|
||||||
|
|
|
||||||
17
BINDINGS.md
17
BINDINGS.md
|
|
@ -6,11 +6,11 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
|
|
||||||
| Name | raylib Version | Language | License |
|
| Name | raylib Version | Language | License |
|
||||||
| :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: |
|
| :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: |
|
||||||
| [raylib](https://github.com/raysan5/raylib) | **5.5** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
|
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
|
||||||
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
|
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
|
||||||
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
|
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
|
||||||
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
|
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
|
||||||
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib55.c3l) | **5.5** | [C3](https://c3-lang.org) | MIT |
|
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
|
||||||
| [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 |
|
||||||
|
|
@ -28,11 +28,12 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
|
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
|
||||||
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
|
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
|
||||||
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
|
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
|
||||||
| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib |
|
| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib |
|
||||||
| [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT |
|
| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT |
|
||||||
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
|
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
|
||||||
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
|
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
|
||||||
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD |
|
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD |
|
||||||
|
| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib |
|
||||||
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
||||||
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
||||||
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
|
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
|
||||||
|
|
@ -63,7 +64,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
||||||
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT |
|
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT |
|
||||||
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
|
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
|
||||||
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
|
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
|
||||||
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
|
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
|
||||||
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
|
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
|
||||||
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
|
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
|
||||||
|
|
@ -76,6 +77,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
|
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
|
||||||
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
||||||
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
|
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||||
|
| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||||
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
|
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
|
||||||
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
|
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
|
||||||
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
||||||
|
|
@ -85,7 +87,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
|
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
|
||||||
| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense |
|
| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense |
|
||||||
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
|
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
|
||||||
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **5.0** | [Vala](https://vala.dev) | Zlib |
|
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
|
||||||
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
|
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
|
||||||
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
|
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
|
||||||
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT |
|
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT |
|
||||||
|
|
@ -104,6 +106,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
| [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/) | **???** |
|
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
|
||||||
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
|
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
|
||||||
|
| [gclang-raylib](https://github.com/gnuchanos/gcLang_Compiler/tree/main/windows_version/raylib_version)| **6.0** | [gclang](https://github.com/gnuchanos/gcLang_Compiler) | AGPL-3.0 |
|
||||||
|
|
||||||
|
|
||||||
### Utility Wrapers
|
### Utility Wrapers
|
||||||
|
|
@ -111,7 +114,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||||
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm.
|
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm.
|
||||||
| Name | raylib Version | Language | License |
|
| Name | raylib Version | Language | License |
|
||||||
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
|
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
|
||||||
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.5** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
|
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **6.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
|
||||||
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
||||||
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
| [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 |
|
||||||
|
|
|
||||||
70
CHANGELOG
70
CHANGELOG
|
|
@ -1,10 +1,10 @@
|
||||||
changelog
|
changelog
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Current Release: raylib 5.5 (18 November 2024)
|
Current Release: raylib 6.0 (23 April 2026)
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
Release: raylib 6.0 (?? March 2026)
|
Release: raylib 6.0 (23 April 2026)
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
KEY CHANGES:
|
KEY CHANGES:
|
||||||
- New Software Renderer backend [rlsw]
|
- New Software Renderer backend [rlsw]
|
||||||
|
|
@ -17,15 +17,21 @@ KEY CHANGES:
|
||||||
- New File System API
|
- New File System API
|
||||||
- New Text Management API
|
- New Text Management API
|
||||||
- New tool: [rexm] raylib examples manager
|
- New tool: [rexm] raylib examples manager
|
||||||
- Added +50 new examples to learn from
|
- Added +70 new examples to learn from
|
||||||
|
|
||||||
Detailed changes:
|
Detailed changes:
|
||||||
|
|
||||||
|
[rcore] ADDED: `FileRename()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileRemove()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileCopy()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileMove()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileTextReplace()`, by @raysan5
|
||||||
|
[rcore] ADDED: `FileTextFindIndex()`, by @raysan5
|
||||||
|
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
||||||
|
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
||||||
[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
|
[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
|
||||||
[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
|
[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
|
||||||
[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
|
[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
|
||||||
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
|
||||||
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
|
||||||
[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
|
[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
|
||||||
[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
|
[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
|
||||||
[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
|
[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
|
||||||
|
|
@ -109,9 +115,10 @@ Detailed changes:
|
||||||
[rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar
|
[rcore][GLFW] REVIEWED: `GetGamepadButtonPressed()`, return GAMEPAD_BUTTON_*_TRIGGER_2 if pressed (#4742) by @whaleymar
|
||||||
[rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC
|
[rcore][GLFW] REVIEWED: Update `mappings.h` using `GenerateMappings.cmake` by @sleeptightAnsiC
|
||||||
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
|
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
|
||||||
|
[rcore][RGFW] ADDED: Support for software rendering (#5773) by @CrackedPixel
|
||||||
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
|
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
|
||||||
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
|
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
|
||||||
[rcore][RGFW] REVIEWED: Duplicate entries reemoved from `keyMappingRGFW` (#5242) by @iamahuman1395
|
[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395
|
||||||
[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
|
[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
|
||||||
[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
|
[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
|
||||||
[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
|
[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
|
||||||
|
|
@ -198,7 +205,7 @@ Detailed changes:
|
||||||
[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
|
[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
|
||||||
[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
|
[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
|
||||||
[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
|
[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
|
||||||
[rlgl] REVIEWED: `SetShaderValueTexture()`, updatee comments (#4703) by @pejorativefox
|
[rlgl] REVIEWED: `SetShaderValueTexture()`, update comments (#4703) by @pejorativefox
|
||||||
[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
|
[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
|
||||||
[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
|
[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
|
||||||
[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
|
[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
|
||||||
|
|
@ -215,6 +222,7 @@ Detailed changes:
|
||||||
[rlsw] REVIEWED: C++ support (#5291) by @alexgb0
|
[rlsw] REVIEWED: C++ support (#5291) by @alexgb0
|
||||||
[rshapes] ADDED: `DrawLineDashed()` (#5222) by @luis605
|
[rshapes] ADDED: `DrawLineDashed()` (#5222) by @luis605
|
||||||
[rshapes] ADDED: `DrawEllipseV()` and `DrawEllipseLinesV()` (#4963) by @meowstr
|
[rshapes] ADDED: `DrawEllipseV()` and `DrawEllipseLinesV()` (#4963) by @meowstr
|
||||||
|
[rshapes] REDESIGNED: `DrawCircleGradient()` to use Vector2 as center parameter by @raysan5 -WARNING-
|
||||||
[rshapes] REVIEWED: `DrawLine()`, fix pixel offset issue on drawing (#4666) by @Bigfoot71
|
[rshapes] REVIEWED: `DrawLine()`, fix pixel offset issue on drawing (#4666) by @Bigfoot71
|
||||||
[rshapes] REVIEWED: `DrawRectangleGradientEx()`, incorrect parameter names (#4980) by @vincent
|
[rshapes] REVIEWED: `DrawRectangleGradientEx()`, incorrect parameter names (#4980) by @vincent
|
||||||
[rshapes] REVIEWED: `DrawRectangleLines`, fix pixel offset issue (#4669) by @Bigfoot71
|
[rshapes] REVIEWED: `DrawRectangleLines`, fix pixel offset issue (#4669) by @Bigfoot71
|
||||||
|
|
@ -239,6 +247,13 @@ Detailed changes:
|
||||||
[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
|
[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
|
||||||
[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
|
[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
|
||||||
[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
|
[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
|
||||||
|
[rtext] ADDED: `TextInsertAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplace()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceBetween()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextReplaceBetweenAlloc()`, returns memory allocated string by @raysan5
|
||||||
|
[rtext] ADDED: `GetTextBetween()`, using static buffer by @raysan5
|
||||||
|
[rtext] ADDED: `TextRemoveSpaces()`, using static buffer by @raysan5
|
||||||
[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
|
[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
|
||||||
[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
|
[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
|
||||||
[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
|
[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
|
||||||
|
|
@ -263,16 +278,16 @@ Detailed changes:
|
||||||
[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
|
[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
|
||||||
[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
|
[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
|
||||||
[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
|
[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
|
||||||
|
[rtext] REVIEWED: `TextInsert()`, use static buffer, easier to use by @raysan5 -WARNING-
|
||||||
[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
|
[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
|
||||||
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
|
||||||
[rtext] REVIEWED: `TextReplace()` by @raysan5
|
|
||||||
[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
|
[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
|
||||||
[rtext] REVIEWED: `TextReplaceBetween()` by @raysan5
|
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
||||||
[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
|
[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
|
||||||
[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
|
[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
|
||||||
[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
|
[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
|
||||||
[rtext] REDESIGNED: `LoadFontData()`, added input parameter by @raysan5 -WARNING-
|
[rtext] REDESIGNED: `LoadFontData()`, added input parameter by @raysan5 -WARNING-
|
||||||
[rmodels] ADDED: Support CPU animation in OpenGL 1.1 (#4925) by @JeffM2501
|
[rmodels] ADDED: Support CPU animation in OpenGL 1.1 (#4925) by @JeffM2501
|
||||||
|
[rmodels] REMOVED: `DrawModelPoints()` and `DrawModelPointsEx()`, moved to an example (#5697) by @maiconpintoabreu -WARNING-
|
||||||
[rmodels] RENAMED: Skinning shader variables (new default naming) by @raysan5
|
[rmodels] RENAMED: Skinning shader variables (new default naming) by @raysan5
|
||||||
[rmodels] REVIEWED: glTF animation framerate calculation (#4472, #5445) by @TheLazyIndianTechie
|
[rmodels] REVIEWED: glTF animation framerate calculation (#4472, #5445) by @TheLazyIndianTechie
|
||||||
[rmodels] REVIEWED: Assign meshes without bone weights to the bone they are attached to so they animate by @Jeffm2501
|
[rmodels] REVIEWED: Assign meshes without bone weights to the bone they are attached to so they animate by @Jeffm2501
|
||||||
|
|
@ -299,6 +314,7 @@ Detailed changes:
|
||||||
[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, properly load 1 frame animations (#5561) by @arlez80
|
[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, properly load 1 frame animations (#5561) by @arlez80
|
||||||
[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, anim correctly inherits world transform (#5206) by @ArmanOmmid
|
[rmodels] REVIEWED: `LoadModelAnimationsGLTF()`, anim correctly inherits world transform (#5206) by @ArmanOmmid
|
||||||
[rmodels] REVIEWED: `UploadMesh()`, improve default normal and tangent values (#4763) by @Bigfoot71
|
[rmodels] REVIEWED: `UploadMesh()`, improve default normal and tangent values (#4763) by @Bigfoot71
|
||||||
|
[rmodels] REVIEWED: `UplaodMesh()`, fix for devices without VAO support (#5692) by @psxdev
|
||||||
[rmodels] REVIEWED: `GenMeshTangents()`, improvements (#4937) by @Bigfoot71
|
[rmodels] REVIEWED: `GenMeshTangents()`, improvements (#4937) by @Bigfoot71
|
||||||
[rmodels] REVIEWED: `UpdateModelAnimation()` optimization (#5244) by @Arrangemonk
|
[rmodels] REVIEWED: `UpdateModelAnimation()` optimization (#5244) by @Arrangemonk
|
||||||
[rmodels] REVIEWED: `UpdateModelAnimationBones()`, break on first mesh found and formating by @raysan5
|
[rmodels] REVIEWED: `UpdateModelAnimationBones()`, break on first mesh found and formating by @raysan5
|
||||||
|
|
@ -310,6 +326,8 @@ Detailed changes:
|
||||||
[rmodels] REVIEWED: `DrawMeshInstanced()`, breaking if instanceTransform was unused (#5469) by @al13n321
|
[rmodels] REVIEWED: `DrawMeshInstanced()`, breaking if instanceTransform was unused (#5469) by @al13n321
|
||||||
[rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski
|
[rmodels] REVIEWED: `DrawSphereEx()`, normals support (#4926) by @karl-zylinski
|
||||||
[rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm
|
[rmodels] REVIEWED: `ExportMesh()`, improve OBJ vertex data precision and lower memory usage (#4496) by @mikeemm
|
||||||
|
[rmodels] REVIEWED: `CheckCollisionSpheres()`, simplified using `Vector3DistanceSqr()` (#5695) by @Bigfoot71
|
||||||
|
[rmodels] REVIEWED: `CheckCollisionBoxSphere()`, improved performance and consistency (#5776) by @maiconpintoabreu
|
||||||
[raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron
|
[raudio] REVIEWED: Fix a glitch at the end of a sound (#5578) by @mackron
|
||||||
[raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron
|
[raudio] REVIEWED: Improvements to device configuration (#5577) by @mackron
|
||||||
[raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501
|
[raudio] REVIEWED: Initialize sound alias properties as if it was a new sound (#5123) by @JeffM2501
|
||||||
|
|
@ -394,11 +412,12 @@ Detailed changes:
|
||||||
[build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral
|
[build][CMake] REVIEWED: Set `libm` as public so it can be linked by consumer (#5193) by @brccabral
|
||||||
[build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2
|
[build][Cmake] REVIEWED: Expose PLATFORM_WEB_RGFW (#5579) by @crisserpl2
|
||||||
[build][Zig] ADDED: Android target to build by @lumenkeyes
|
[build][Zig] ADDED: Android target to build by @lumenkeyes
|
||||||
|
[build][Zig] REDESIGNED: Complete refactor of build.zig to support Zig 0.16.0 (#5764) by @HaxSam
|
||||||
[build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes
|
[build][Zig] REVIEWED: Link EGL for Android by @lumenkeyes
|
||||||
[build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam
|
[build][Zig] REVIEWED: Approach to build for web with zig-build (#5157) by @haxsam
|
||||||
[build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki
|
[build][Zig] REVIEWED: Fix build accessing env vars (#5490) by @iisakki
|
||||||
[build][Zig] REVIEWED: Fix emscripten building by @johnnymarler
|
[build][Zig] REVIEWED: Fix emscripten building by @johnnymarler
|
||||||
[build][Zig] REVIWED: Move examples/build.zig into main build.zig by @johnnymarler
|
[build][Zig] REVIEWED: Move examples/build.zig into main build.zig by @johnnymarler
|
||||||
[build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik
|
[build][Zig] REVIEWED: Fix raygui inclusion in windows crosscompilation (#4489) by @kimierik
|
||||||
[build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415
|
[build][Zig] REVIEWED: Issue on emscripten run if the user has not installed emsdk by @emilhakimov415
|
||||||
[build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik
|
[build][Zig] REVIEWED: Make X11 the default display backend instead of choosing at runtime (#5168) by @Not-Nik
|
||||||
|
|
@ -446,6 +465,7 @@ Detailed changes:
|
||||||
[examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary
|
[examples] ADDED: `shapes_rlgl_triangle` example (#5353) by @robinsaviary
|
||||||
[examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates
|
[examples] ADDED: `shapes_starfield` (#5255) by @themushroompirates
|
||||||
[examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe
|
[examples] ADDED: `shapes_triangle_strip` (#5240) by @Jopestpe
|
||||||
|
[examples] ADDED: `shapes_collision_ellipses` (#5722) by @Monjaris
|
||||||
[examples] ADDED: `text_inline_styling` by @raysan5
|
[examples] ADDED: `text_inline_styling` by @raysan5
|
||||||
[examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto
|
[examples] ADDED: `text_strings_management` (#5379) by @davidbuzatto
|
||||||
[examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates
|
[examples] ADDED: `text_words_alignment` (#5254) by @themushroompirates
|
||||||
|
|
@ -735,7 +755,7 @@ Detailed changes:
|
||||||
[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
|
[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
|
||||||
[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
|
[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
|
||||||
[rexm] REVIEWED: `examples.js` example addition working by @raysan5
|
[rexm] REVIEWED: `examples.js` example addition working by @raysan5
|
||||||
[rexm] REVIEWED: `add` command logic for existing examplee addition by @raysan5
|
[rexm] REVIEWED: `add` command logic for existing example addition by @raysan5
|
||||||
[rexm] REVIEWED: Replace example name on project file by @raysan5
|
[rexm] REVIEWED: Replace example name on project file by @raysan5
|
||||||
[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
|
[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
|
||||||
[rexm] REVIEWED: VS project adding to solution by @raysan5
|
[rexm] REVIEWED: VS project adding to solution by @raysan5
|
||||||
|
|
@ -747,6 +767,7 @@ Detailed changes:
|
||||||
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
||||||
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
||||||
|
|
||||||
|
[external] ADDED: `cgltf_write` 1.15, to support glTF models export in the future, by @raysan5
|
||||||
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
||||||
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
||||||
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
||||||
|
|
@ -755,16 +776,23 @@ Detailed changes:
|
||||||
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
||||||
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
||||||
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
||||||
|
[external] UPDATED: `raygui` to 5.0-dev for examples by @raysan5
|
||||||
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
||||||
[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX
|
[external] UPDATED: `miniaudio` to v0.11.22 (#4983) by @M374LX
|
||||||
[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8
|
[external] UPDATED: `miniaudio` to v0.11.23 (#5234) by @pyrokn8
|
||||||
[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak
|
[external] UPDATED: `miniaudio` to v0.11.24 (#5506) by @vdemcak
|
||||||
[external] UPDATED: raygui to 5.0-dev for examples by @raysan5
|
[external] UPDATED: `RGFW` to 1.5 (#4688) by @ColleagueRiley
|
||||||
[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley
|
[external] UPDATED: `RGFW` to 1.6 (#4795) by @colleagueRiley
|
||||||
[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley
|
[external] UPDATED: `RGFW` to 1.7 (#4965) by @M374LX
|
||||||
[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX
|
[external] UPDATED: `RGFW` to 1.7.5-dev (#4976) by @M374LX
|
||||||
[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX
|
[external] UPDATED: `RGFW` to 2.0.0 (#5582) by @CrackedPixel
|
||||||
[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel
|
[external] UPDATED: `cgltf` 1.14 to 1.15 by @raysan5
|
||||||
|
[external] UPDATED: `dr_flac` v0.13.0 to v0.13.3 by @raysan5
|
||||||
|
[external] UPDATED: `dr_mp3` v0.7.0 to v0.7.4 by @raysan5
|
||||||
|
[external] UPDATED: `m3d` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `qoi` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `qoa` to latest master by @raysan5
|
||||||
|
[external] UPDATED: `stb_image_resize2` v2.12 to v2.18 by @raysan5
|
||||||
|
|
||||||
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
||||||
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ if(EMSCRIPTEN)
|
||||||
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
|
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
|
||||||
SET(PLATFORM Web CACHE STRING "Platform to build for.")
|
SET(PLATFORM Web CACHE STRING "Platform to build for.")
|
||||||
endif()
|
endif()
|
||||||
enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW" "Platform to build for.")
|
enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
|
||||||
|
|
||||||
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
|
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
|
||||||
|
|
||||||
|
|
@ -29,11 +29,15 @@ option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF)
|
||||||
option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON)
|
option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON)
|
||||||
|
|
||||||
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF)
|
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF)
|
||||||
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
|
|
||||||
|
|
||||||
include(ParseConfigHeader)
|
include(ParseConfigHeader)
|
||||||
|
|
||||||
foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS)
|
foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS)
|
||||||
string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG})
|
string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG})
|
||||||
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CMAKE_MATCH_2} CUSTOMIZE_BUILD ${CMAKE_MATCH_2})
|
set(CONFIG_HEADER_FLAG_DEFAULT ${CMAKE_MATCH_2})
|
||||||
|
if (INCLUDE_EVERYTHING AND "${CONFIG_HEADER_FLAG_DEFAULT}" STREQUAL "OFF")
|
||||||
|
set(CONFIG_HEADER_FLAG_DEFAULT ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CONFIG_HEADER_FLAG_DEFAULT} CUSTOMIZE_BUILD ${CONFIG_HEADER_FLAG_DEFAULT})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
||||||
85
HISTORY.md
85
HISTORY.md
|
|
@ -526,26 +526,79 @@ Last but not least, I want to thank **raylib sponsors and all the raylib communi
|
||||||
notes on raylib 6.0
|
notes on raylib 6.0
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
A new raylib release is finally ready, after almost 1.5 years since last release. This is the biggest release ever with many improvements to the library, thanks to the support of many amazing contributors and also thanks to the financial support of NLnet/NGI0 funds.
|
A new `raylib` release is finally ready and, again, this is the **biggest `raylib` release ever**! Thanks to the support of many amazing contributors this release comes packed with many new features and improvements, also thanks to the financial support of [NLnet](https://nlnet.nl/) and the [NGI Zero Commond Fund](https://nlnet.nl/NGI0/) that allow me to work on this project mostly fulltime for the past few months.
|
||||||
|
|
||||||
Some astonishing numbers for this release:
|
Some astonishing numbers for this release:
|
||||||
|
|
||||||
- **+320** closed issues (for a TOTAL of **+2130**!)
|
- **+330** closed issues (for a TOTAL of **+2150**!)
|
||||||
- **+1800** commits since previous RELEASE (for a TOTAL of **+9600**!)
|
- **+2000** commits since previous RELEASE (for a TOTAL of **+9760**!)
|
||||||
- **18** functions ADDED to raylib API (for a TOTAL of **599**!)
|
- **+20** new functions ADDED to raylib API (for a TOTAL of **600**!)
|
||||||
- **+50** new examples to learn from (for a TOTAL of **212**!)
|
- **+70** new examples to learn from (for a TOTAL of **+215**!)
|
||||||
- **+200** new contributors (for a TOTAL of **+840**!)
|
- **+210** new contributors (for a TOTAL of **+850**!)
|
||||||
|
|
||||||
Highlights for `raylib 6.0`:
|
Highlights for `raylib 6.0`:
|
||||||
|
|
||||||
- New Software Renderer backend [rlsw]
|
- **`NEW` Software Renderer - [`rlsw`](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h)**: The biggest addition of this new release. A new software renderer backend, that allows raylib to run purely on CPU, with no neeed for a GPU. It finally closes the circle of my search for a portable self-contained, with **no-external-dependencies**, graphics library, able to run on any device providing some CPU-power and some RAM memory. It has been possible thanks to the amazing work of **Le Juez Victor** ([@Bigfoot71](https://github.com/Bigfoot71)), who created [`rlsw`](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h), a single-file header-only library implementing OpenGL 1.1+ specification, tailored to fit into raylib [`rlgl`](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) OpenGL wrapper, and allowing to run raylib seamlessly over CPU with **no code changes required on user side**. As expected, software rendering is slower than hardware-accelerated rendering but it is still fast enough to run basic application at 30-60 fps. Actually, it already proved it usefulness on a new [raylib port for ESP32](https://components.espressif.com/components/georgik/raylib/versions/6.0.0/readme) microcontroller by Espressif, useful for industrial applications, and opens the door to the upcoming RISC-V powered devices that start arriving to the marked, and many times come with no GPU. Along the new software renderer, some of the existing platform backends have been adapted to support it (SDL, RGFW, DRM) and also **new platforms backends have been created** to accomodate it (Win32, Emscripten), incluing a new `PLATFORM_MEMORY`, that allows direct rendering to a memory framebuffer.
|
||||||
- New rcore platform backend: Memory (memory buffer)
|
|
||||||
- New rcore platform backend: Win32 (experimental)
|
|
||||||
- New rcore platform backend: Emscripten (experimental)
|
|
||||||
- Redesigned Skeletal Animation System
|
|
||||||
- Redesigned fullscreen modes and high-dpi content scaling
|
|
||||||
- Redesigned Build Config System [config.h]
|
|
||||||
- New File System API
|
|
||||||
- New Text Management API
|
|
||||||
- New tool: [rexm] raylib examples manager
|
|
||||||
|
|
||||||
|
- **`NEW` Platform backend: Memory - [`rcore_memory`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_memory.c)**: This new platform has been added along the **software renderer** backend, allowing 2d and 3d rendering over a **platform-agnostic memory framebuffer**, it can run headless and output frames can be directly exported to images. This new backend could also be useful for graphics rendering on servers or process images directly using the memory buffer.
|
||||||
|
|
||||||
|
- **`NEW` Platform backend: Win32 - [`rcore_desktop_win32`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_desktop_win32.c)**: A new **Windows platform backend** and the first step towards a potential replacement/alternative to the platform libraries currently used by raylib (GLFW/SDL/RGFW). This backend follows same API template structure than the other raylib backends, but directly implementing Win32 API calls. It allows initializing OpenGL GPU-accelerated windows and also GDI based windows, useful for the software renderer backend. This new backend approach, following a common template-structure and separating the platform logic by specific OS/Windowing system, will simplify code, improve maintenance, readability and portability for raylib, setting some bases for the future. *NOTE: This backend is new and it could require further testing, use it as an experimental backend for now.*
|
||||||
|
|
||||||
|
- **`NEW` Platform backend: Emscripten - [`rcore_web_emscripten`](https://github.com/raysan5/raylib/blob/master/src/platforms/rcore_web_emscripten.c)**: In the same line as Win32 backend, this new web backend moves away from `libglfw.js` and **directly implements Emscripten/JS functionality**, with **no other dependencies**, adding support for the new software renderer to draw directly on a **non-accelerated 2d canvas** but also supporting a WebGL-hardware-accelerated canvas when required. *NOTE: This backend is new and it could require further testing, use it as an experimental backend for now.*
|
||||||
|
|
||||||
|
- **`REDESIGNED` Fullscreen modes and High-DPI content scaling**: After many years and many related issues, the full-screen and high-dpi content scaling support has been **completely redesigned** from scratch. New design prioritizes **borderless fullscreen modes** and automatically detects current monitor content scaling configuration to scale window and framebuffer accordingly when required. Still, High-DPI support must be requested by user if desired enabling `FLAG_WINDOW_HIGHDPI` on window creation. This new system has been carefully tested on Windows, Linux (X11, Wayland), macOS with multiple monitors and multiple resolutions, including 4K monitors.
|
||||||
|
|
||||||
|
- **`REDESIGNED` Skeletal Animation System**: A new animation system for 3d models has been created to support animation blending, between single frames but also between differents frames on different animations, to allow easy **timed transitions** between animations. This redesign implied reviewing several raylib structures to better accomodate animation data: `Model`, `ModelSkeleton`, `ModelAnimation`, but the API was simplified and support for GPU-skinning was improved with multiple optimizations.
|
||||||
|
|
||||||
|
- **`REDESIGNED` Build Config System - [`config.h`](https://github.com/raysan5/raylib/blob/master/src/config.h)**: raylib allows lot of customization for specific needs (i.e. disabling modules not needed for specific applications like rmodels or raudio) but previous implementation did not allow easely disabling some features from **custom build systems**. New design not only allows disabling features with simple `-DSUPPORT_FILEFORMAT_OBJ=0` on building command-line but also the full system has been reviewed, removing useless flags and exposing new ones.
|
||||||
|
|
||||||
|
- **`NEW` File System API**: Along the years, multiple filesystem functions have been added to raylib API as required but it felt somewhat inconsistent with some pieces missing. In this new release, the full filesystem API has beeen reviewed and reorganized, compiling all the functionality single module: [rcore](https://github.com/raysan5/raylib/blob/master/src/raylib.h#L1126), consequently `utils` module has been removed and build system has been simplified even more; **only 6-7 modules (.c) need to be compiled containing the full raylib library**. This new filesystem API will allow raylib to be used on the creation of custom build systems, as already demostrated with the new `rexm` tool for examples management. At the moment raylib includes **+40 file system management functions**, here a list with the new functions added:
|
||||||
|
```c
|
||||||
|
int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists)
|
||||||
|
int FileRemove(const char *fileName); // Remove file (if exists)
|
||||||
|
int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist
|
||||||
|
int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist
|
||||||
|
int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file
|
||||||
|
int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`NEW` Text Management API**: Along with the new file system functionality, a new set of text management functions has been added, also very useful for text procesing and also used in custom build systems creation using raylib. At the moment raylib includes **+30 text management functions**, here a list with the new functions added:
|
||||||
|
```c
|
||||||
|
char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||||
|
void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||||
|
const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||||
|
char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||||
|
char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||||
|
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||||
|
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||||
|
char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||||
|
char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`NEW` tool: raylib examples manager - [rexm](https://github.com/raysan5/raylib/tree/master/tools/rexm)**: raylib examples collection is huge, with **more than 200 examples** it was quite difficult to manage: adding, removing, renaming examples was a very costly process involving many files to be modified (including build systems), also the examples did not follow a common header convention neither a structure conventions. For that reason, a new support tool has been created: **rexm**, a raylib examples manager that allows to easely add/remove/rename examples, automatically fix inconsistencies and even **building and automated testing** on multiple platforms.
|
||||||
|
```
|
||||||
|
USAGE:
|
||||||
|
> rexm <command> <example_name> [<example_rename>]
|
||||||
|
|
||||||
|
COMMANDS:
|
||||||
|
create <new_example_name> : Creates an empty example, from internal template
|
||||||
|
add <example_name> : Add existing example to collection
|
||||||
|
rename <old_examples_name> <new_example_name> : Rename an existing example
|
||||||
|
remove <example_name> : Remove an existing example from collection
|
||||||
|
build <example_name> : Build example for Desktop and Web platforms
|
||||||
|
test <example_name> : Build and Test example for Desktop and Web platforms
|
||||||
|
validate : Validate examples collection, generates report
|
||||||
|
update : Validate and update examples collection, generates report
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`NEW` +70 new examples**: Thanks to `rexm` and the simplification on examples management, this new raylib release includes +70 new examples to learn from, most of them contributed by community. Multiple examples have also been renamed for consistency and all examples header and structure have been reviewed and unified.
|
||||||
|
|
||||||
|
Make sure to check raylib [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) for a detailed list of changes!
|
||||||
|
|
||||||
|
I want to **thank all the contributors (+850!**) that along the years have **greatly improved raylib** and pushed it further and better day after day. And **many thanks to raylib community and all raylib users** for supporting the library along those many years.
|
||||||
|
|
||||||
|
Finally, I want to thank [puffer.ai](https://puffer.ai/) and [comma.ai](https://comma.ai/) for **using raylib and supporting the project** as platinum sponsors, along many others individuals that have been sponsoring raylib along the years. Thanks to all of you for allowing me to keep working on this library!
|
||||||
|
|
||||||
|
**After +12 years of development, `raylib 6.0` is today one of the bests libraries to enjoy games/tools/graphics programming!**
|
||||||
|
|
||||||
|
**Enjoy graphics programming with raylib!** :)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
|
||||||
|
|
||||||
[](https://github.com/raysan5/raylib/releases)
|
[](https://github.com/raysan5/raylib/releases)
|
||||||
[](https://github.com/raysan5/raylib/stargazers)
|
[](https://github.com/raysan5/raylib/stargazers)
|
||||||
[](https://github.com/raysan5/raylib/commits/master)
|
[](https://github.com/raysan5/raylib/commits/master)
|
||||||
[](https://github.com/sponsors/raysan5)
|
[](https://github.com/sponsors/raysan5)
|
||||||
[](https://repology.org/project/raylib/versions)
|
[](https://repology.org/project/raylib/versions)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
@ -40,6 +40,7 @@ features
|
||||||
- Written in plain C code (C99) using PascalCase/camelCase notation
|
- Written in plain C code (C99) using PascalCase/camelCase notation
|
||||||
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
||||||
- **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h)
|
- **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h)
|
||||||
|
- **Software Renderer** backend (no OpenGL required!): [rlsw](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h)
|
||||||
- Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts)
|
- Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts)
|
||||||
- Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC)
|
- Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC)
|
||||||
- **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more!
|
- **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more!
|
||||||
|
|
@ -61,7 +62,7 @@ This is a basic raylib example, it creates a window and draws the text `"Congrat
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
InitWindow(800, 450, "raylib [core] example - basic window");
|
InitWindow(800, 450, "raylib example - basic window");
|
||||||
|
|
||||||
while (!WindowShouldClose())
|
while (!WindowShouldClose())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ Here is a wishlist with features and ideas to improve the library. Note that fea
|
||||||
- [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed.
|
- [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed.
|
||||||
- [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve.
|
- [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve.
|
||||||
- raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment:
|
- raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment:
|
||||||
|
- [raylib 7.0 wishlist](https://github.com/raysan5/raylib/discussions/5710)
|
||||||
- [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660)
|
- [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660)
|
||||||
- [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952)
|
- [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952)
|
||||||
- [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272)
|
- [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272)
|
||||||
|
|
@ -21,8 +22,9 @@ _Current version of raylib is complete and functional but there is always room f
|
||||||
- [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
|
- [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
|
||||||
- [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
|
- [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
|
||||||
- [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
|
- [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
|
||||||
- [ ] `rtextures`: Consider moving N-patch system to separate example
|
- [ ] `rtextures`: Consider removing N-patch system, provide as separate example
|
||||||
- [ ] `rtextures`: Review blending modes system, provide more options or better samples
|
- [ ] `rtextures`: Review blending modes system, provide more options or better samples
|
||||||
|
- [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm
|
||||||
- [ ] `raudio`: Support microphone input, basic API to read microphone
|
- [ ] `raudio`: Support microphone input, basic API to read microphone
|
||||||
- [ ] `rltexgpu`: Improve compressed textures support, loading and saving, improve KTX 2.0
|
- [ ] `rltexgpu`: Improve compressed textures support, loading and saving, improve KTX 2.0
|
||||||
- [ ] `rlobj`: Create OBJ loader, supporting material file separately (low priority)
|
- [ ] `rlobj`: Create OBJ loader, supporting material file separately (low priority)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
.{
|
.{
|
||||||
.name = .raylib,
|
.name = .raylib,
|
||||||
.version = "5.6.0-dev",
|
.version = "6.0.0",
|
||||||
.minimum_zig_version = "0.15.1",
|
.minimum_zig_version = "0.16.0",
|
||||||
|
|
||||||
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
|
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.xcode_frameworks = .{
|
.xcode_frameworks = .{
|
||||||
.url = "git+https://github.com/hexops/xcode-frameworks#9a45f3ac977fd25dff77e58c6de1870b6808c4a7",
|
.url = "https://pkg.machengine.org/xcode-frameworks/8a1cfb373587ea4c9bb1468b7c986462d8d4e10e.tar.gz",
|
||||||
.hash = "N-V-__8AABHMqAWYuRdIlflwi8gksPnlUMQBiSxAqQAAZFms",
|
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
|
||||||
|
.lazy = true,
|
||||||
|
},
|
||||||
|
.raygui = .{
|
||||||
|
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
|
||||||
|
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
.emsdk = .{
|
.emsdk = .{
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,30 @@ if(POLICY CMP0072)
|
||||||
cmake_policy(SET CMP0072 NEW)
|
cmake_policy(SET CMP0072 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
|
||||||
|
function(raylib_check_libatomic_required result)
|
||||||
|
set(_atomic_test_source "
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
volatile long long value = 0;
|
||||||
|
return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST);
|
||||||
|
}")
|
||||||
|
|
||||||
|
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||||
|
|
||||||
|
if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||||
|
set(${result} FALSE PARENT_SCOPE)
|
||||||
|
else ()
|
||||||
|
cmake_push_check_state()
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
|
||||||
|
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC)
|
||||||
|
cmake_pop_check_state()
|
||||||
|
set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE)
|
||||||
|
endif ()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
|
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
|
||||||
|
|
||||||
if (${PLATFORM} STREQUAL "Desktop")
|
if (${PLATFORM} STREQUAL "Desktop")
|
||||||
|
|
@ -67,6 +91,21 @@ if (${PLATFORM} STREQUAL "Desktop")
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
elseif (${PLATFORM} STREQUAL "Win32")
|
||||||
|
if ((NOT WIN32) AND (NOT CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64"))
|
||||||
|
message(FATAL_ERROR "Win32 platform requires Windows or a cross compiler.")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PLATFORM_CPP "PLATFORM_DESKTOP_WIN32")
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
|
if (${OPENGL_VERSION} MATCHES "Software")
|
||||||
|
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_package(OpenGL QUIET)
|
||||||
|
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
|
||||||
|
|
||||||
elseif (${PLATFORM} STREQUAL "Web")
|
elseif (${PLATFORM} STREQUAL "Web")
|
||||||
set(PLATFORM_CPP "PLATFORM_WEB")
|
set(PLATFORM_CPP "PLATFORM_WEB")
|
||||||
if(NOT GRAPHICS)
|
if(NOT GRAPHICS)
|
||||||
|
|
@ -96,21 +135,30 @@ elseif (${PLATFORM} STREQUAL "Android")
|
||||||
|
|
||||||
elseif ("${PLATFORM}" STREQUAL "DRM")
|
elseif ("${PLATFORM}" STREQUAL "DRM")
|
||||||
set(PLATFORM_CPP "PLATFORM_DRM")
|
set(PLATFORM_CPP "PLATFORM_DRM")
|
||||||
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
|
|
||||||
|
|
||||||
add_definitions(-D_DEFAULT_SOURCE)
|
add_definitions(-D_DEFAULT_SOURCE)
|
||||||
add_definitions(-DEGL_NO_X11)
|
|
||||||
add_definitions(-DPLATFORM_DRM)
|
add_definitions(-DPLATFORM_DRM)
|
||||||
|
|
||||||
find_library(GLESV2 GLESv2)
|
|
||||||
find_library(EGL EGL)
|
|
||||||
find_library(DRM drm)
|
find_library(DRM drm)
|
||||||
find_library(GBM gbm)
|
|
||||||
|
|
||||||
if (NOT CMAKE_CROSSCOMPILING OR NOT CMAKE_SYSROOT)
|
if (NOT CMAKE_CROSSCOMPILING OR NOT CMAKE_SYSROOT)
|
||||||
include_directories(/usr/include/libdrm)
|
include_directories(/usr/include/libdrm)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if ("${OPENGL_VERSION}" STREQUAL "Software")
|
||||||
|
# software rendering does not require EGL/GBM.
|
||||||
|
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
|
||||||
|
set(LIBS_PRIVATE ${DRM} atomic pthread dl)
|
||||||
|
else ()
|
||||||
|
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
|
||||||
|
add_definitions(-DEGL_NO_X11)
|
||||||
|
|
||||||
|
find_library(GLESV2 GLESv2)
|
||||||
|
find_library(EGL EGL)
|
||||||
|
find_library(GBM gbm)
|
||||||
|
|
||||||
set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread dl)
|
set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread dl)
|
||||||
|
endif ()
|
||||||
set(LIBS_PUBLIC m)
|
set(LIBS_PUBLIC m)
|
||||||
|
|
||||||
elseif ("${PLATFORM}" STREQUAL "SDL")
|
elseif ("${PLATFORM}" STREQUAL "SDL")
|
||||||
|
|
@ -147,6 +195,7 @@ elseif ("${PLATFORM}" STREQUAL "SDL")
|
||||||
add_compile_definitions(USING_SDL2_PACKAGE)
|
add_compile_definitions(USING_SDL2_PACKAGE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
elseif ("${PLATFORM}" STREQUAL "RGFW")
|
elseif ("${PLATFORM}" STREQUAL "RGFW")
|
||||||
set(PLATFORM_CPP "PLATFORM_DESKTOP_RGFW")
|
set(PLATFORM_CPP "PLATFORM_DESKTOP_RGFW")
|
||||||
|
|
||||||
|
|
@ -172,6 +221,15 @@ elseif ("${PLATFORM}" STREQUAL "WebRGFW")
|
||||||
set(PLATFORM_CPP "PLATFORM_WEB_RGFW")
|
set(PLATFORM_CPP "PLATFORM_WEB_RGFW")
|
||||||
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
|
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
|
||||||
set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
|
set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
|
||||||
|
|
||||||
|
elseif ("${PLATFORM}" STREQUAL "Memory")
|
||||||
|
set(PLATFORM_CPP "PLATFORM_MEMORY")
|
||||||
|
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
|
||||||
|
set(OPENGL_VERSION "Software")
|
||||||
|
|
||||||
|
if(WIN32 OR CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64")
|
||||||
|
set(LIBS_PRIVATE winmm)
|
||||||
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT ${OPENGL_VERSION} MATCHES "OFF")
|
if (NOT ${OPENGL_VERSION} MATCHES "OFF")
|
||||||
|
|
@ -203,6 +261,14 @@ endif ()
|
||||||
|
|
||||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
|
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
|
||||||
|
|
||||||
|
if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE)
|
||||||
|
raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED)
|
||||||
|
if (RAYLIB_LIBATOMIC_REQUIRED)
|
||||||
|
message(STATUS "64-bit atomics require libatomic")
|
||||||
|
list(APPEND LIBS_PRIVATE atomic)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (${PLATFORM} MATCHES "Desktop")
|
if (${PLATFORM} MATCHES "Desktop")
|
||||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
|
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ string(REGEX MATCHALL ${MACRO_REGEX} MACRO_LIST ${CONFIG_HEADER_CONTENT})
|
||||||
set(CONFIG_HEADER_FLAGS ${MACRO_LIST})
|
set(CONFIG_HEADER_FLAGS ${MACRO_LIST})
|
||||||
list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_")
|
list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_")
|
||||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//")
|
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//")
|
||||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=ON]])
|
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=\3]] REGEX "^[^/]")
|
||||||
|
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=0$]] [[=OFF]])
|
||||||
|
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=1$]] [[=ON]])
|
||||||
|
|
||||||
set(CONFIG_HEADER_VALUES ${MACRO_LIST})
|
set(CONFIG_HEADER_VALUES ${MACRO_LIST})
|
||||||
list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)")
|
list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)")
|
||||||
|
|
|
||||||
|
|
@ -98,13 +98,15 @@ if (${PLATFORM} MATCHES "Android")
|
||||||
|
|
||||||
elseif (${PLATFORM} MATCHES "Web")
|
elseif (${PLATFORM} MATCHES "Web")
|
||||||
set(example_sources) # clear example_sources
|
set(example_sources) # clear example_sources
|
||||||
list(APPEND example_sources others/web_basic_window.c)
|
|
||||||
list(APPEND example_sources core/core_input_gestures_testbed.c)
|
list(APPEND example_sources core/core_input_gestures_testbed.c)
|
||||||
|
|
||||||
elseif ("${PLATFORM}" STREQUAL "DRM")
|
elseif ("${PLATFORM}" STREQUAL "DRM")
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||||
|
|
||||||
|
elseif ("${PLATFORM}" MATCHES "Memory")
|
||||||
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||||
|
|
||||||
elseif ("${OPENGL_VERSION}" STREQUAL "Software")
|
elseif ("${OPENGL_VERSION}" STREQUAL "Software")
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
# - Linux (X11 desktop mode)
|
# - Linux (X11 desktop mode)
|
||||||
# - macOS/OSX (x64, arm64 (not tested))
|
# - macOS/OSX (x64, arm64 (not tested))
|
||||||
# - Others (not tested)
|
# - Others (not tested)
|
||||||
|
# > PLATFORM_DESKTOP_WIN32 (native Win32):
|
||||||
|
# - Windows (Win32, Win64)
|
||||||
# > PLATFORM_WEB_RGFW:
|
# > PLATFORM_WEB_RGFW:
|
||||||
# - HTML5 (WebAssembly)
|
# - HTML5 (WebAssembly)
|
||||||
# > PLATFORM_WEB:
|
# > PLATFORM_WEB:
|
||||||
|
|
@ -510,7 +512,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
|
||||||
# Libraries for Windows desktop compilation
|
# Libraries for Windows desktop compilation
|
||||||
LDFLAGS += -L..\src
|
LDFLAGS += -L..\src
|
||||||
LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore
|
LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore
|
||||||
ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE)
|
ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
LDLIBS += -lopengl32
|
LDLIBS += -lopengl32
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
@ -794,6 +796,23 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
|
||||||
|
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||||
|
del *.o *.exe /s
|
||||||
|
endif
|
||||||
|
ifeq ($(PLATFORM_OS),BSD)
|
||||||
|
find . -type f -perm -ugo+x -delete
|
||||||
|
rm -fv *.o
|
||||||
|
endif
|
||||||
|
ifeq ($(PLATFORM_OS),LINUX)
|
||||||
|
find . -type f -executable -delete
|
||||||
|
rm -fv *.o
|
||||||
|
endif
|
||||||
|
ifeq ($(PLATFORM_OS),OSX)
|
||||||
|
find . -type f -perm +ugo+x -delete
|
||||||
|
rm -f *.o
|
||||||
|
endif
|
||||||
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||||
find . -type f -executable -delete
|
find . -type f -executable -delete
|
||||||
rm -fv *.o
|
rm -fv *.o
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# raylib makefile for Android project (APK building)
|
# raylib makefile for Android project (APK building)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
|
# Copyright (c) 2017-2026 Ramon Santamaria (@raysan5)
|
||||||
#
|
#
|
||||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
# will the authors be held liable for any damages arising from the use of this software.
|
# will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -1153,7 +1153,10 @@ text/text_font_filters: text/text_font_filters.c
|
||||||
--preload-file text/resources/KAISG.ttf@resources/KAISG.ttf
|
--preload-file text/resources/KAISG.ttf@resources/KAISG.ttf
|
||||||
|
|
||||||
text/text_font_loading: text/text_font_loading.c
|
text/text_font_loading: text/text_font_loading.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||||
|
--preload-file text/resources/pixantiqua.fnt@resources/pixantiqua.fnt \
|
||||||
|
--preload-file text/resources/pixantiqua.png@resources/pixantiqua.png \
|
||||||
|
--preload-file text/resources/pixantiqua.ttf@resources/pixantiqua.ttf
|
||||||
|
|
||||||
text/text_font_sdf: text/text_font_sdf.c
|
text/text_font_sdf: text/text_font_sdf.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||||
|
|
|
||||||
238
examples/audio/audio_amp_envelope.c
Normal file
238
examples/audio/audio_amp_envelope.c
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [audio] example - amp envelope
|
||||||
|
*
|
||||||
|
* Example complexity rating: [★☆☆☆] 1/4
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||||
|
*
|
||||||
|
* Example contributed by Arbinda Rizki Muhammad (@arbipink) 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) 2026 Arbinda Rizki Muhammad (@arbipink)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#define RAYGUI_IMPLEMENTATION
|
||||||
|
#include "raygui.h"
|
||||||
|
|
||||||
|
#include <math.h> // Required for: sinf()
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 4096
|
||||||
|
#define SAMPLE_RATE 44100
|
||||||
|
|
||||||
|
// Wave state
|
||||||
|
typedef enum {
|
||||||
|
IDLE,
|
||||||
|
ATTACK,
|
||||||
|
DECAY,
|
||||||
|
SUSTAIN,
|
||||||
|
RELEASE
|
||||||
|
} ADSRState;
|
||||||
|
|
||||||
|
// Grouping all ADSR parameters and state into a struct
|
||||||
|
typedef struct {
|
||||||
|
float attackTime;
|
||||||
|
float decayTime;
|
||||||
|
float sustainLevel;
|
||||||
|
float releaseTime;
|
||||||
|
float currentValue;
|
||||||
|
ADSRState state;
|
||||||
|
} Envelope;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime);
|
||||||
|
static void UpdateEnvelope(Envelope *env);
|
||||||
|
static void DrawADSRGraph(Envelope *env, Rectangle bounds);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [audio] example - amp envelope");
|
||||||
|
|
||||||
|
InitAudioDevice();
|
||||||
|
|
||||||
|
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||||
|
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||||
|
float buffer[BUFFER_SIZE] = { 0 };
|
||||||
|
|
||||||
|
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||||
|
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||||
|
|
||||||
|
// Init Phase
|
||||||
|
float audioTime = 0.0f;
|
||||||
|
|
||||||
|
// Initialize the struct
|
||||||
|
Envelope env = {
|
||||||
|
.attackTime = 1.0f,
|
||||||
|
.decayTime = 1.0f,
|
||||||
|
.sustainLevel = 0.5f,
|
||||||
|
.releaseTime = 1.0f,
|
||||||
|
.currentValue = 0.0f,
|
||||||
|
.state = IDLE
|
||||||
|
};
|
||||||
|
|
||||||
|
SetTargetFPS(60);
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose())
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK;
|
||||||
|
|
||||||
|
if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE;
|
||||||
|
|
||||||
|
if (IsAudioStreamProcessed(stream))
|
||||||
|
{
|
||||||
|
if ((env.state != IDLE) || (env.currentValue > 0.0f))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||||
|
{
|
||||||
|
UpdateEnvelope(&env);
|
||||||
|
FillAudioBuffer(i, buffer, env.currentValue, &audioTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear buffer if silent to avoid looping noise
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0;
|
||||||
|
audioTime = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAudioStream(stream, buffer, BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsAudioStreamPlaying(stream)) PlayAudioStream(stream);
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
GuiSliderBar((Rectangle){ 100, 60, 400, 30 }, "Attack (s)", TextFormat("%2.2fs", env.attackTime), &env.attackTime, 0.1f, 3.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 100, 400, 30 }, "Decay (s)", TextFormat("%2.2fs", env.decayTime), &env.decayTime, 0.1f, 3.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 140, 400, 30 }, "Sustain", TextFormat("%2.2f", env.sustainLevel), &env.sustainLevel, 0.0f, 1.0f);
|
||||||
|
GuiSliderBar((Rectangle){ 100, 180, 400, 30 }, "Release (s)", TextFormat("%2.2fs", env.releaseTime), &env.releaseTime, 0.1f, 3.0f);
|
||||||
|
|
||||||
|
DrawADSRGraph(&env, (Rectangle){ 100, 250, 400, 100 });
|
||||||
|
|
||||||
|
DrawCircleV((Vector2){ 520, 350 - (env.currentValue * 100) }, 5, MAROON);
|
||||||
|
DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON);
|
||||||
|
|
||||||
|
DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadAudioStream(stream);
|
||||||
|
CloseAudioDevice();
|
||||||
|
|
||||||
|
CloseWindow();
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime)
|
||||||
|
{
|
||||||
|
int frequency = 440;
|
||||||
|
buffer[i] = envelopeValue*sinf(2.0f*PI*frequency*(*audioTime));
|
||||||
|
*audioTime += (1.0f/SAMPLE_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateEnvelope(Envelope *env)
|
||||||
|
{
|
||||||
|
// Calculate the time delta for ONE sample (1/44100)
|
||||||
|
float sampleTime = 1.0f/SAMPLE_RATE;
|
||||||
|
|
||||||
|
switch(env->state)
|
||||||
|
{
|
||||||
|
case ATTACK:
|
||||||
|
{
|
||||||
|
env->currentValue += (1.0f/env->attackTime)*sampleTime;
|
||||||
|
if (env->currentValue >= 1.0f)
|
||||||
|
{
|
||||||
|
env->currentValue = 1.0f;
|
||||||
|
env->state = DECAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case DECAY:
|
||||||
|
{
|
||||||
|
env->currentValue -= ((1.0f - env->sustainLevel)/env->decayTime)*sampleTime;
|
||||||
|
if (env->currentValue <= env->sustainLevel)
|
||||||
|
{
|
||||||
|
env->currentValue = env->sustainLevel;
|
||||||
|
env->state = SUSTAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SUSTAIN:
|
||||||
|
{
|
||||||
|
env->currentValue = env->sustainLevel;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case RELEASE:
|
||||||
|
{
|
||||||
|
env->currentValue -= (env->sustainLevel/env->releaseTime)*sampleTime;
|
||||||
|
if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail
|
||||||
|
{
|
||||||
|
env->currentValue = 0.0f;
|
||||||
|
env->state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawADSRGraph(Envelope *env, Rectangle bounds)
|
||||||
|
{
|
||||||
|
DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f));
|
||||||
|
DrawRectangleLinesEx(bounds, 1, GRAY);
|
||||||
|
|
||||||
|
// Fixed visual width for sustain stage since it's an amplitude not a time value
|
||||||
|
float sustainWidth = 1.0f;
|
||||||
|
|
||||||
|
// Total time to visualize (sum of A, D, R + a padding for Sustain)
|
||||||
|
float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime;
|
||||||
|
|
||||||
|
float scaleX = bounds.width/totalTime;
|
||||||
|
float scaleY = bounds.height;
|
||||||
|
|
||||||
|
Vector2 start = { bounds.x, bounds.y + bounds.height };
|
||||||
|
Vector2 peak = { start.x + (env->attackTime*scaleX), bounds.y };
|
||||||
|
Vector2 sustain = { peak.x + (env->decayTime*scaleX), bounds.y + (1.0f - env->sustainLevel)*scaleY };
|
||||||
|
Vector2 rel = { sustain.x + (sustainWidth*scaleX), sustain.y };
|
||||||
|
Vector2 end = { rel.x + (env->releaseTime*scaleX), bounds.y + bounds.height };
|
||||||
|
|
||||||
|
DrawLineV(start, peak, SKYBLUE);
|
||||||
|
DrawLineV(peak, sustain, BLUE);
|
||||||
|
DrawLineV(sustain, rel, DARKBLUE);
|
||||||
|
DrawLineV(rel, end, ORANGE);
|
||||||
|
|
||||||
|
DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY);
|
||||||
|
}
|
||||||
BIN
examples/audio/audio_amp_envelope.png
Normal file
BIN
examples/audio/audio_amp_envelope.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
6051
examples/audio/raygui.h
Normal file
6051
examples/audio/raygui.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -22,7 +22,7 @@
|
||||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
* BSD-like license that allows static linking with closed source software
|
* BSD-like license that allows static linking with closed source software
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "raygui.h" // Required for GUI controls
|
#include "raygui.h" // Required for GUI controls
|
||||||
|
|
||||||
#define MAX_FILEPATH_SIZE 1024
|
#define MAX_FILEPATH_SIZE 1024
|
||||||
|
#define FILE_FILTER "DIRS*;.png;.c"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
|
|
@ -41,7 +42,7 @@ int main(void)
|
||||||
// NOTE: LoadDirectoryFiles() loads files and directories by default,
|
// NOTE: LoadDirectoryFiles() loads files and directories by default,
|
||||||
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
|
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
|
||||||
//FilePathList files = LoadDirectoryFiles(directory);
|
//FilePathList files = LoadDirectoryFiles(directory);
|
||||||
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
|
FilePathList files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||||
|
|
||||||
int btnBackPressed = false;
|
int btnBackPressed = false;
|
||||||
|
|
||||||
|
|
@ -61,7 +62,22 @@ int main(void)
|
||||||
{
|
{
|
||||||
TextCopy(directory, GetPrevDirectoryPath(directory));
|
TextCopy(directory, GetPrevDirectoryPath(directory));
|
||||||
UnloadDirectoryFiles(files);
|
UnloadDirectoryFiles(files);
|
||||||
files = LoadDirectoryFiles(directory);
|
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||||
|
|
||||||
|
listScrollIndex = 0;
|
||||||
|
listItemActive = -1;
|
||||||
|
listItemFocused = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((listItemActive >= 0) && (listItemActive < (int)files.count) && DirectoryExists(files.paths[listItemActive]))
|
||||||
|
{
|
||||||
|
TextCopy(directory, files.paths[listItemActive]);
|
||||||
|
UnloadDirectoryFiles(files);
|
||||||
|
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||||
|
|
||||||
|
listScrollIndex = 0;
|
||||||
|
listItemActive = -1;
|
||||||
|
listItemFocused = -1;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
free(rectangles);
|
RL_FREE(rectangles);
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ int main(void)
|
||||||
|
|
||||||
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
|
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
|
||||||
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
|
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
|
||||||
Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
|
Rectangle destRec = { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
|
||||||
|
|
||||||
Vector2 origin = { 0.0f, 0.0f };
|
Vector2 origin = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
|
@ -61,6 +61,9 @@ int main(void)
|
||||||
float cameraX = 0.0f;
|
float cameraX = 0.0f;
|
||||||
float cameraY = 0.0f;
|
float cameraY = 0.0f;
|
||||||
|
|
||||||
|
bool smoothOn = true;
|
||||||
|
bool overscan = false;
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -86,6 +89,18 @@ int main(void)
|
||||||
worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y);
|
worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y);
|
||||||
screenSpaceCamera.target.y -= worldSpaceCamera.target.y;
|
screenSpaceCamera.target.y -= worldSpaceCamera.target.y;
|
||||||
screenSpaceCamera.target.y *= virtualRatio;
|
screenSpaceCamera.target.y *= virtualRatio;
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_S)) smoothOn = !smoothOn;
|
||||||
|
if (IsKeyPressed(KEY_O)) overscan = !overscan;
|
||||||
|
|
||||||
|
if (overscan)
|
||||||
|
{
|
||||||
|
destRec = (Rectangle) { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destRec = (Rectangle) { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
|
@ -101,14 +116,23 @@ int main(void)
|
||||||
EndTextureMode();
|
EndTextureMode();
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RED);
|
ClearBackground(LIGHTGRAY);
|
||||||
|
|
||||||
|
if (smoothOn)
|
||||||
|
{
|
||||||
BeginMode2D(screenSpaceCamera);
|
BeginMode2D(screenSpaceCamera);
|
||||||
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
|
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
|
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
|
||||||
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
|
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
|
||||||
|
DrawText(TextFormat("Smooth: %s", (smoothOn ? "ON" : "OFF")), 10, screenHeight - 60, 20, RED);
|
||||||
|
DrawText(TextFormat("Overscan: %s", (overscan ? "ON" : "OFF")), 10, screenHeight - 30, 20, RED);
|
||||||
DrawFPS(GetScreenWidth() - 95, 10);
|
DrawFPS(GetScreenWidth() - 95, 10);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 3.4 KiB |
1422
examples/example_resources.zon
Normal file
1422
examples/example_resources.zon
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,8 @@
|
||||||
GLFW_ICON ICON "raylib.ico"
|
GLFW_ICON ICON "raylib.ico"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 5,5,0,0
|
FILEVERSION 6,0,0,0
|
||||||
PRODUCTVERSION 5,5,0,0
|
PRODUCTVERSION 6,0,0,0
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
@ -11,12 +11,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "raylib technologies"
|
VALUE "CompanyName", "raylib technologies"
|
||||||
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
||||||
VALUE "FileVersion", "5.5.0"
|
VALUE "FileVersion", "6.0.0"
|
||||||
VALUE "InternalName", "raylib-example"
|
VALUE "InternalName", "raylib-example"
|
||||||
VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)"
|
VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)"
|
||||||
VALUE "OriginalFilename", "raylib-example"
|
VALUE "OriginalFilename", "raylib-example"
|
||||||
VALUE "ProductName", "raylib-example"
|
VALUE "ProductName", "raylib-example"
|
||||||
VALUE "ProductVersion", "5.5.0"
|
VALUE "ProductVersion", "6.0.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ int main(void)
|
||||||
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
||||||
|
|
||||||
bool showModel = true;
|
bool showModel = true;
|
||||||
Model decalModels[MAX_DECALS] = { 0 };
|
static Model decalModels[MAX_DECALS] = { 0 };
|
||||||
int decalCount = 0;
|
int decalCount = 0;
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
#include "rlgl.h"
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: rand()
|
#include <stdlib.h> // Required for: rand()
|
||||||
#include <math.h> // Required for: cosf(), sinf()
|
#include <math.h> // Required for: cosf(), sinf()
|
||||||
|
|
@ -26,8 +27,9 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Generate mesh using points
|
static Mesh GenMeshPoints(int numPoints); // Generate mesh using points
|
||||||
static Mesh GenMeshPoints(int numPoints);
|
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
||||||
|
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
|
|
@ -184,3 +186,30 @@ static Mesh GenMeshPoints(int numPoints)
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Draw a model points
|
||||||
|
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||||
|
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
||||||
|
{
|
||||||
|
rlEnablePointMode();
|
||||||
|
rlDisableBackfaceCulling();
|
||||||
|
|
||||||
|
DrawModel(model, position, scale, tint);
|
||||||
|
|
||||||
|
rlEnableBackfaceCulling();
|
||||||
|
rlDisablePointMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a model points
|
||||||
|
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||||
|
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
||||||
|
{
|
||||||
|
rlEnablePointMode();
|
||||||
|
rlDisableBackfaceCulling();
|
||||||
|
|
||||||
|
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
||||||
|
|
||||||
|
rlEnableBackfaceCulling();
|
||||||
|
rlDisablePointMode();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ int main(void)
|
||||||
|
|
||||||
Model model = LoadModel("resources/models/obj/plane.obj"); // Load model
|
Model model = LoadModel("resources/models/obj/plane.obj"); // Load model
|
||||||
Texture2D texture = LoadTexture("resources/models/obj/plane_diffuse.png"); // Load model texture
|
Texture2D texture = LoadTexture("resources/models/obj/plane_diffuse.png"); // Load model texture
|
||||||
|
|
||||||
|
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT); // Force Repeat to avoid issue on Web version
|
||||||
|
|
||||||
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
||||||
|
|
||||||
float pitch = 0.0f;
|
float pitch = 0.0f;
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@
|
||||||
| models/vox/chr_knight.vox | ❔ | ❔ | - |
|
| models/vox/chr_knight.vox | ❔ | ❔ | - |
|
||||||
| models/vox/chr_sword.vox | ❔ | ❔ | - |
|
| models/vox/chr_sword.vox | ❔ | ❔ | - |
|
||||||
| models/vox/monu9.vox | ❔ | ❔ | - |
|
| models/vox/monu9.vox | ❔ | ❔ | - |
|
||||||
| billboard.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| billboard.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| cubicmap_atlas.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| cubicmap_atlas.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||||
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||||
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ void main()
|
||||||
|
|
||||||
float specCo = 0.0;
|
float specCo = 0.0;
|
||||||
|
|
||||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||||
|
|
||||||
specular += specCo;
|
specular += specCo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ int main(void)
|
||||||
DrawText("USING DEFAULT SHADER", 20, 40, 10, RED);
|
DrawText("USING DEFAULT SHADER", 20, 40, 10, RED);
|
||||||
|
|
||||||
DrawCircle(80, 120, 35, DARKBLUE);
|
DrawCircle(80, 120, 35, DARKBLUE);
|
||||||
DrawCircleGradient(80, 220, 60, GREEN, SKYBLUE);
|
DrawCircleGradient((Vector2){ 80.0f, 220.0f }, 60, GREEN, SKYBLUE);
|
||||||
DrawCircleLines(80, 340, 80, DARKBLUE);
|
DrawCircleLines(80, 340, 80, DARKBLUE);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ int main(void)
|
||||||
// Set the texture tiling using a shader
|
// Set the texture tiling using a shader
|
||||||
float tiling[2] = { 3.0f, 3.0f };
|
float tiling[2] = { 3.0f, 3.0f };
|
||||||
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION));
|
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION));
|
||||||
|
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT);
|
||||||
SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2);
|
SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2);
|
||||||
model.materials[0].shader = shader;
|
model.materials[0].shader = shader;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,21 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include "raymath.h"
|
||||||
#include <math.h>
|
|
||||||
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
|
#include <math.h> // Required for: hypot()
|
||||||
|
|
||||||
#define MAX_BALLS 5000 // Maximum quantity of balls
|
#define MAX_BALLS 5000 // Maximum quantity of balls
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Ball data type
|
||||||
typedef struct Ball {
|
typedef struct Ball {
|
||||||
Vector2 pos; // Position
|
Vector2 position;
|
||||||
Vector2 vel; // Velocity
|
Vector2 speed;
|
||||||
Vector2 ppos; // Previous position
|
Vector2 prevPosition;
|
||||||
float radius;
|
float radius;
|
||||||
float friction;
|
float friction;
|
||||||
float elasticity;
|
float elasticity;
|
||||||
|
|
@ -45,11 +51,13 @@ int main(void)
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ball physics");
|
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ball physics");
|
||||||
|
|
||||||
Ball *balls = (Ball*)malloc(sizeof(Ball)*MAX_BALLS);
|
Ball *balls = (Ball*)RL_MALLOC(sizeof(Ball)*MAX_BALLS);
|
||||||
|
|
||||||
|
// Init first ball in the array
|
||||||
balls[0] = (Ball){
|
balls[0] = (Ball){
|
||||||
.pos = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f },
|
.position = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f },
|
||||||
.vel = { 200, 200 },
|
.speed = { 200, 200 },
|
||||||
.ppos = { 0 },
|
.prevPosition = { 0 },
|
||||||
.radius = 40,
|
.radius = 40,
|
||||||
.friction = 0.99f,
|
.friction = 0.99f,
|
||||||
.elasticity = 0.9f,
|
.elasticity = 0.9f,
|
||||||
|
|
@ -63,6 +71,8 @@ int main(void)
|
||||||
|
|
||||||
float gravity = 100; // World gravity
|
float gravity = 100; // World gravity
|
||||||
|
|
||||||
|
Vector2 windowPosition = GetWindowPosition();
|
||||||
|
|
||||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -80,8 +90,8 @@ int main(void)
|
||||||
for (int i = ballCount - 1; i >= 0; i--)
|
for (int i = ballCount - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Ball *ball = &balls[i];
|
Ball *ball = &balls[i];
|
||||||
pressOffset.x = mousePos.x - ball->pos.x;
|
pressOffset.x = mousePos.x - ball->position.x;
|
||||||
pressOffset.y = mousePos.y - ball->pos.y;
|
pressOffset.y = mousePos.y - ball->position.y;
|
||||||
|
|
||||||
// If the distance between the ball position and the mouse press position
|
// If the distance between the ball position and the mouse press position
|
||||||
// is less than or equal to the ball radius, the event occurred inside the ball
|
// is less than or equal to the ball radius, the event occurred inside the ball
|
||||||
|
|
@ -110,9 +120,9 @@ int main(void)
|
||||||
if (ballCount < MAX_BALLS)
|
if (ballCount < MAX_BALLS)
|
||||||
{
|
{
|
||||||
balls[ballCount++] = (Ball){
|
balls[ballCount++] = (Ball){
|
||||||
.pos = mousePos,
|
.position = mousePos,
|
||||||
.vel = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) },
|
.speed = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) },
|
||||||
.ppos = { 0 },
|
.prevPosition = { 0 },
|
||||||
.radius = 20.0f + (float)GetRandomValue(0, 30),
|
.radius = 20.0f + (float)GetRandomValue(0, 30),
|
||||||
.friction = 0.99f,
|
.friction = 0.99f,
|
||||||
.elasticity = 0.9f,
|
.elasticity = 0.9f,
|
||||||
|
|
@ -122,12 +132,23 @@ int main(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get window position change for shaking
|
||||||
|
Vector2 windowPositionDelta = Vector2Subtract(windowPosition, GetWindowPosition());
|
||||||
|
|
||||||
|
if (Vector2Length(windowPositionDelta) > 5.0f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ballCount; i++)
|
||||||
|
{
|
||||||
|
if (!balls[i].grabbed) balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDelta, 10.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Shake balls
|
// Shake balls
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ballCount; i++)
|
for (int i = 0; i < ballCount; i++)
|
||||||
{
|
{
|
||||||
if (!balls[i].grabbed) balls[i].vel = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) };
|
if (!balls[i].grabbed) balls[i].speed = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,51 +164,53 @@ int main(void)
|
||||||
if (!ball->grabbed)
|
if (!ball->grabbed)
|
||||||
{
|
{
|
||||||
// Ball repositioning using the velocity
|
// Ball repositioning using the velocity
|
||||||
ball->pos.x += ball->vel.x * delta;
|
ball->position.x += ball->speed.x * delta;
|
||||||
ball->pos.y += ball->vel.y * delta;
|
ball->position.y += ball->speed.y * delta;
|
||||||
|
|
||||||
// Does the ball hit the screen right boundary?
|
// Does the ball hit the screen right boundary?
|
||||||
if ((ball->pos.x + ball->radius) >= screenWidth)
|
if ((ball->position.x + ball->radius) >= screenWidth)
|
||||||
{
|
{
|
||||||
ball->pos.x = screenWidth - ball->radius; // Ball repositioning
|
ball->position.x = screenWidth - ball->radius; // Ball repositioning
|
||||||
ball->vel.x = -ball->vel.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit
|
ball->speed.x = -ball->speed.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit
|
||||||
}
|
}
|
||||||
// Does the ball hit the screen left boundary?
|
// Does the ball hit the screen left boundary?
|
||||||
else if ((ball->pos.x - ball->radius) <= 0)
|
else if ((ball->position.x - ball->radius) <= 0)
|
||||||
{
|
{
|
||||||
ball->pos.x = ball->radius;
|
ball->position.x = ball->radius;
|
||||||
ball->vel.x = -ball->vel.x*ball->elasticity;
|
ball->speed.x = -ball->speed.x*ball->elasticity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The same for y axis
|
// The same for y axis
|
||||||
if ((ball->pos.y + ball->radius) >= screenHeight)
|
if ((ball->position.y + ball->radius) >= screenHeight)
|
||||||
{
|
{
|
||||||
ball->pos.y = screenHeight - ball->radius;
|
ball->position.y = screenHeight - ball->radius;
|
||||||
ball->vel.y = -ball->vel.y*ball->elasticity;
|
ball->speed.y = -ball->speed.y*ball->elasticity;
|
||||||
}
|
}
|
||||||
else if ((ball->pos.y - ball->radius) <= 0)
|
else if ((ball->position.y - ball->radius) <= 0)
|
||||||
{
|
{
|
||||||
ball->pos.y = ball->radius;
|
ball->position.y = ball->radius;
|
||||||
ball->vel.y = -ball->vel.y*ball->elasticity;
|
ball->speed.y = -ball->speed.y*ball->elasticity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Friction makes the ball lose 1% of its velocity each frame
|
// Friction makes the ball lose 1% of its velocity each frame
|
||||||
ball->vel.x = ball->vel.x*ball->friction;
|
ball->speed.x = ball->speed.x*ball->friction;
|
||||||
// Gravity affects only the y axis
|
// Gravity affects only the y axis
|
||||||
ball->vel.y = ball->vel.y*ball->friction + gravity;
|
ball->speed.y = ball->speed.y*ball->friction + gravity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ball repositioning using the mouse position
|
// Ball repositioning using the mouse position
|
||||||
ball->pos.x = mousePos.x - pressOffset.x;
|
ball->position.x = mousePos.x - pressOffset.x;
|
||||||
ball->pos.y = mousePos.y - pressOffset.y;
|
ball->position.y = mousePos.y - pressOffset.y;
|
||||||
|
|
||||||
// While the ball is grabbed, recalculates its velocity
|
// While the ball is grabbed, recalculates its velocity
|
||||||
ball->vel.x = (ball->pos.x - ball->ppos.x)/delta;
|
ball->speed.x = (ball->position.x - ball->prevPosition.x)/delta;
|
||||||
ball->vel.y = (ball->pos.y - ball->ppos.y)/delta;
|
ball->speed.y = (ball->position.y - ball->prevPosition.y)/delta;
|
||||||
ball->ppos = ball->pos;
|
ball->prevPosition = ball->position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowPosition = GetWindowPosition();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
|
@ -198,8 +221,8 @@ int main(void)
|
||||||
|
|
||||||
for (int i = 0; i < ballCount; i++)
|
for (int i = 0; i < ballCount; i++)
|
||||||
{
|
{
|
||||||
DrawCircleV(balls[i].pos, balls[i].radius, balls[i].color);
|
DrawCircleV(balls[i].position, balls[i].radius, balls[i].color);
|
||||||
DrawCircleLinesV(balls[i].pos, balls[i].radius, BLACK);
|
DrawCircleLinesV(balls[i].position, balls[i].radius, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawText("grab a ball by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY);
|
DrawText("grab a ball by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY);
|
||||||
|
|
@ -215,7 +238,8 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
free(balls);
|
RL_FREE(balls);
|
||||||
|
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ int main(void)
|
||||||
|
|
||||||
// Circle shapes and lines
|
// Circle shapes and lines
|
||||||
DrawCircle(screenWidth/5, 120, 35, DARKBLUE);
|
DrawCircle(screenWidth/5, 120, 35, DARKBLUE);
|
||||||
DrawCircleGradient(screenWidth/5, 220, 60, GREEN, SKYBLUE);
|
DrawCircleGradient((Vector2){ screenWidth/5.0f, 220.0f }, 60, GREEN, SKYBLUE);
|
||||||
DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE);
|
DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE);
|
||||||
DrawEllipse(screenWidth/5, 120, 25, 20, YELLOW);
|
DrawEllipse(screenWidth/5, 120, 25, 20, YELLOW);
|
||||||
DrawEllipseLines(screenWidth/5, 120, 30, 25, YELLOW);
|
DrawEllipseLines(screenWidth/5, 120, 30, 25, YELLOW);
|
||||||
|
|
|
||||||
133
examples/shapes/shapes_ellipse_collision.c
Normal file
133
examples/shapes/shapes_ellipse_collision.c
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [shapes] example - ellipse collision
|
||||||
|
*
|
||||||
|
* Example complexity rating: [★★☆☆] 2/4
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||||
|
*
|
||||||
|
* Example contributed by Ziya (@Monjaris)
|
||||||
|
*
|
||||||
|
* 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 Ziya (@Monjaris)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// Check if point is inside ellipse
|
||||||
|
static bool CheckCollisionPointEllipse(Vector2 point, Vector2 center, float rx, float ry)
|
||||||
|
{
|
||||||
|
float dx = (point.x - center.x)/rx;
|
||||||
|
float dy = (point.y - center.y)/ry;
|
||||||
|
return (dx*dx + dy*dy) <= 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if two ellipses collide
|
||||||
|
// Uses radial boundary distance in the direction between centers — scales correctly with radii
|
||||||
|
static bool CheckCollisionEllipses(Vector2 c1, float rx1, float ry1, Vector2 c2, float rx2, float ry2)
|
||||||
|
{
|
||||||
|
float dx = c2.x - c1.x;
|
||||||
|
float dy = c2.y - c1.y;
|
||||||
|
float dist = sqrtf(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
// Ellipses are on top of each other
|
||||||
|
if (dist == 0.0f) return true;
|
||||||
|
|
||||||
|
float theta = atan2f(dy, dx);
|
||||||
|
float cosT = cosf(theta);
|
||||||
|
float sinT = sinf(theta);
|
||||||
|
|
||||||
|
// Radial distance from center to ellipse boundary in direction theta
|
||||||
|
// r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2)
|
||||||
|
float r1 = (rx1*ry1)/sqrtf((ry1*cosT)*(ry1*cosT) + (rx1*sinT)*(rx1*sinT));
|
||||||
|
float r2 = (rx2*ry2)/sqrtf((ry2*cosT)*(ry2*cosT) + (rx2*sinT)*(rx2*sinT));
|
||||||
|
|
||||||
|
return dist <= (r1 + r2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
|
||||||
|
SetTargetFPS(60);
|
||||||
|
|
||||||
|
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };
|
||||||
|
float ellipseARx = 120.0f;
|
||||||
|
float ellipseARy = 70.0f;
|
||||||
|
|
||||||
|
Vector2 ellipseBCenter = { (float)screenWidth*3/4, (float)screenHeight/2 };
|
||||||
|
float ellipseBRx = 90.0f;
|
||||||
|
float ellipseBRy = 140.0f;
|
||||||
|
|
||||||
|
// 0 = controlling A, 1 = controlling B
|
||||||
|
int controlled = 0;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if (IsKeyPressed(KEY_A)) controlled = 0;
|
||||||
|
if (IsKeyPressed(KEY_B)) controlled = 1;
|
||||||
|
|
||||||
|
if (controlled == 0) ellipseACenter = GetMousePosition();
|
||||||
|
else ellipseBCenter = GetMousePosition();
|
||||||
|
|
||||||
|
bool ellipsesCollide = CheckCollisionEllipses(
|
||||||
|
ellipseACenter, ellipseARx, ellipseARy,
|
||||||
|
ellipseBCenter, ellipseBRx, ellipseBRy
|
||||||
|
);
|
||||||
|
|
||||||
|
bool mouseInA = CheckCollisionPointEllipse(GetMousePosition(), ellipseACenter, ellipseARx, ellipseARy);
|
||||||
|
bool mouseInB = CheckCollisionPointEllipse(GetMousePosition(), ellipseBCenter, ellipseBRx, ellipseBRy);
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
DrawEllipse((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, ellipsesCollide ? RED : BLUE);
|
||||||
|
|
||||||
|
DrawEllipse((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, ellipsesCollide ? RED : GREEN);
|
||||||
|
|
||||||
|
DrawEllipseLines((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, WHITE);
|
||||||
|
|
||||||
|
DrawEllipseLines((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, WHITE);
|
||||||
|
|
||||||
|
DrawCircleV(ellipseACenter, 4, WHITE);
|
||||||
|
DrawCircleV(ellipseBCenter, 4, WHITE);
|
||||||
|
|
||||||
|
if (ellipsesCollide) DrawText("ELLIPSES COLLIDE", screenWidth/2 - 120, 40, 28, RED);
|
||||||
|
else DrawText("NO COLLISION", screenWidth/2 - 80, 40, 28, DARKGRAY);
|
||||||
|
|
||||||
|
DrawText(controlled == 0 ? "Controlling: A" : "Controlling: B", 20, screenHeight - 40, 20, YELLOW);
|
||||||
|
|
||||||
|
if (mouseInA && controlled != 0) DrawText("Mouse inside ellipse A", 20, screenHeight - 70, 20, BLUE);
|
||||||
|
if (mouseInB && controlled != 1) DrawText("Mouse inside ellipse B", 20, screenHeight - 70, 20, GREEN);
|
||||||
|
|
||||||
|
DrawText("Press [A] or [B] to switch control", 20, 20, 20, GRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
CloseWindow();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
examples/shapes/shapes_ellipse_collision.png
Normal file
BIN
examples/shapes/shapes_ellipse_collision.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -341,7 +341,7 @@ static void DrawLightMask(int slot)
|
||||||
rlSetBlendMode(BLEND_CUSTOM);
|
rlSetBlendMode(BLEND_CUSTOM);
|
||||||
|
|
||||||
// If we are valid, then draw the light radius to the alpha mask
|
// If we are valid, then draw the light radius to the alpha mask
|
||||||
if (lights[slot].valid) DrawCircleGradient((int)lights[slot].position.x, (int)lights[slot].position.y, lights[slot].outerRadius, ColorAlpha(WHITE, 0), WHITE);
|
if (lights[slot].valid) DrawCircleGradient(lights[slot].position, lights[slot].outerRadius, ColorAlpha(WHITE, 0), WHITE);
|
||||||
|
|
||||||
rlDrawRenderBatchActive();
|
rlDrawRenderBatchActive();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ int main(void)
|
||||||
SetTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n')
|
SetTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||||
|
|
||||||
// Free codepoints, atlas has already been generated
|
// Free codepoints, atlas has already been generated
|
||||||
free(codepointsNoDups);
|
RL_FREE(codepointsNoDups);
|
||||||
|
|
||||||
bool showFontAtlas = false;
|
bool showFontAtlas = false;
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ int main(void)
|
||||||
static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount)
|
static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount)
|
||||||
{
|
{
|
||||||
int codepointsNoDupsCount = codepointCount;
|
int codepointsNoDupsCount = codepointCount;
|
||||||
int *codepointsNoDups = (int *)calloc(codepointCount, sizeof(int));
|
int *codepointsNoDups = (int *)RL_CALLOC(codepointCount, sizeof(int));
|
||||||
memcpy(codepointsNoDups, codepoints, codepointCount*sizeof(int));
|
memcpy(codepointsNoDups, codepoints, codepointCount*sizeof(int));
|
||||||
|
|
||||||
// Remove duplicates
|
// Remove duplicates
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ int main(void)
|
||||||
|
|
||||||
// Define characters to draw
|
// Define characters to draw
|
||||||
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
||||||
const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
const char msg[256] = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||||
|
|
||||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||||
|
|
||||||
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
||||||
Font fontBm = LoadFont("resources/pixantiqua.fnt");
|
Font fontBm = LoadFont("resources/pixantiqua.fnt"); // Requires "resources/pixantiqua.png"
|
||||||
|
|
||||||
// TTF font : Font data and atlas are generated directly from TTF
|
// TTF font : Font data and atlas are generated directly from TTF
|
||||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ int main(void)
|
||||||
// Load bunny texture
|
// Load bunny texture
|
||||||
Texture2D texBunny = LoadTexture("resources/raybunny.png");
|
Texture2D texBunny = LoadTexture("resources/raybunny.png");
|
||||||
|
|
||||||
Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array
|
Bunny *bunnies = (Bunny *)RL_MALLOC(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array
|
||||||
|
|
||||||
int bunniesCount = 0; // Bunnies counter
|
int bunniesCount = 0; // Bunnies counter
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
free(bunnies); // Unload bunnies data array
|
RL_FREE(bunnies); // Unload bunnies data array
|
||||||
|
|
||||||
UnloadTexture(texBunny); // Unload bunny texture
|
UnloadTexture(texBunny); // Unload bunny texture
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ int main(void)
|
||||||
|
|
||||||
// If the mouse is on this preset, highlight it
|
// If the mouse is on this preset, highlight it
|
||||||
if (mouseInCell == i + 8)
|
if (mouseInCell == i + 8)
|
||||||
DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*((float)i/2),
|
DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*(i/2),
|
||||||
(presetsSizeY + 2.0f)*(i%2),
|
(presetsSizeY + 2.0f)*(i%2),
|
||||||
presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED);
|
presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ int main(void)
|
||||||
// NOTE: We can have up to 256 values for tile ids and for tile fog state,
|
// NOTE: We can have up to 256 values for tile ids and for tile fog state,
|
||||||
// probably we don't need that many values for fog state, it can be optimized
|
// probably we don't need that many values for fog state, it can be optimized
|
||||||
// to use only 2 bits per fog state (reducing size by 4) but logic will be a bit more complex
|
// to use only 2 bits per fog state (reducing size by 4) but logic will be a bit more complex
|
||||||
map.tileIds = (unsigned char *)calloc(map.tilesX*map.tilesY, sizeof(unsigned char));
|
map.tileIds = (unsigned char *)RL_CALLOC(map.tilesX*map.tilesY, sizeof(unsigned char));
|
||||||
map.tileFog = (unsigned char *)calloc(map.tilesX*map.tilesY, sizeof(unsigned char));
|
map.tileFog = (unsigned char *)RL_CALLOC(map.tilesX*map.tilesY, sizeof(unsigned char));
|
||||||
|
|
||||||
// Load map tiles (generating 2 random tile ids for testing)
|
// Load map tiles (generating 2 random tile ids for testing)
|
||||||
// NOTE: Map tile ids should be probably loaded from an external map file
|
// NOTE: Map tile ids should be probably loaded from an external map file
|
||||||
|
|
@ -149,8 +149,8 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
free(map.tileIds); // Free allocated map tile ids
|
RL_FREE(map.tileIds); // Free allocated map tile ids
|
||||||
free(map.tileFog); // Free allocated map tile fog state
|
RL_FREE(map.tileFog); // Free allocated map tile fog state
|
||||||
|
|
||||||
UnloadRenderTexture(fogOfWar); // Unload render texture
|
UnloadRenderTexture(fogOfWar); // Unload render texture
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc() and free()
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -39,26 +37,31 @@ int main(void)
|
||||||
UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data
|
UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data
|
||||||
|
|
||||||
// Generate a checked texture by code
|
// Generate a checked texture by code
|
||||||
int width = 960;
|
int imWidth = 960;
|
||||||
int height = 480;
|
int imHeight = 480;
|
||||||
|
|
||||||
// Dynamic memory allocation to store pixels data (Color type)
|
// Dynamic memory allocation to store pixels data (Color type)
|
||||||
Color *pixels = (Color *)malloc(width*height*sizeof(Color));
|
// WARNING: Using raylib provided MemAlloc() that uses default raylib
|
||||||
|
// internal memory allocator, so this data can be freed using UnloadImage()
|
||||||
|
// that also uses raylib internal memory de-allocator
|
||||||
|
Color *pixels = (Color *)MemAlloc(imWidth*imHeight*sizeof(Color));
|
||||||
|
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < imHeight; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x++)
|
for (int x = 0; x < imWidth; x++)
|
||||||
{
|
{
|
||||||
if (((x/32+y/32)/1)%2 == 0) pixels[y*width + x] = ORANGE;
|
if (((x/32+y/32)/1)%2 == 0) pixels[y*imWidth + x] = ORANGE;
|
||||||
else pixels[y*width + x] = GOLD;
|
else pixels[y*imWidth + x] = GOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load pixels data into an image structure and create texture
|
// Load pixels data into an image structure and create texture
|
||||||
|
// NOTE: We can assign pixels directly to data because Color is R8G8B8A8
|
||||||
|
// data structure defining that pixelformat, format must be set properly
|
||||||
Image checkedIm = {
|
Image checkedIm = {
|
||||||
.data = pixels, // We can assign pixels directly to data
|
.data = pixels,
|
||||||
.width = width,
|
.width = imWidth,
|
||||||
.height = height,
|
.height = imHeight,
|
||||||
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
|
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
|
||||||
.mipmaps = 1
|
.mipmaps = 1
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ project(example)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
set(RAYLIB_VERSION 5.5)
|
set(RAYLIB_VERSION 6.0)
|
||||||
find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED
|
find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED
|
||||||
if (NOT raylib_FOUND) # If there's none, fetch and build raylib
|
if (NOT raylib_FOUND) # If there's none, fetch and build raylib
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -191,7 +191,7 @@
|
||||||
<Overload retVal="const char" descr="Get clipboard text content"></Overload>
|
<Overload retVal="const char" descr="Get clipboard text content"></Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="GetClipboardImage" func="yes">
|
<KeyWord name="GetClipboardImage" func="yes">
|
||||||
<Overload retVal="Image" descr="Get clipboard image"></Overload>
|
<Overload retVal="Image" descr="Get clipboard image content"></Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="EnableEventWaiting" func="yes">
|
<KeyWord name="EnableEventWaiting" func="yes">
|
||||||
<Overload retVal="void" descr="Enable waiting for events on EndDrawing(), no automatic event polling"></Overload>
|
<Overload retVal="void" descr="Enable waiting for events on EndDrawing(), no automatic event polling"></Overload>
|
||||||
|
|
@ -360,7 +360,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="SetShaderValueTexture" func="yes">
|
<KeyWord name="SetShaderValueTexture" func="yes">
|
||||||
<Overload retVal="void" descr="Set shader uniform value for texture (sampler2d)">
|
<Overload retVal="void" descr="Set shader uniform value and bind the texture (sampler2d)">
|
||||||
<Param name="Shader shader" />
|
<Param name="Shader shader" />
|
||||||
<Param name="int locIndex" />
|
<Param name="int locIndex" />
|
||||||
<Param name="Texture2D texture" />
|
<Param name="Texture2D texture" />
|
||||||
|
|
@ -498,8 +498,12 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
<!-- NOTE: Following functions implemented in module [utils] -->
|
<!-- Logging system -->
|
||||||
<!-------------------------------------------------------------------- -->
|
<KeyWord name="SetTraceLogLevel" func="yes">
|
||||||
|
<Overload retVal="void" descr="Set the current threshold (minimum) log level">
|
||||||
|
<Param name="int logLevel" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="TraceLog" func="yes">
|
<KeyWord name="TraceLog" func="yes">
|
||||||
<Overload retVal="void" descr="Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)">
|
<Overload retVal="void" descr="Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)">
|
||||||
<Param name="int logLevel" />
|
<Param name="int logLevel" />
|
||||||
|
|
@ -507,11 +511,13 @@
|
||||||
<Param name="..." />
|
<Param name="..." />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="SetTraceLogLevel" func="yes">
|
<KeyWord name="SetTraceLogCallback" func="yes">
|
||||||
<Overload retVal="void" descr="Set the current threshold (minimum) log level">
|
<Overload retVal="void" descr="Set custom trace log">
|
||||||
<Param name="int logLevel" />
|
<Param name="TraceLogCallback callback" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
|
<!-- Memory management, using internal allocators -->
|
||||||
<KeyWord name="MemAlloc" func="yes">
|
<KeyWord name="MemAlloc" func="yes">
|
||||||
<Overload retVal="void" descr="Internal memory allocator">
|
<Overload retVal="void" descr="Internal memory allocator">
|
||||||
<Param name="unsigned int size" />
|
<Param name="unsigned int size" />
|
||||||
|
|
@ -524,35 +530,7 @@
|
||||||
<Overload retVal="void" descr="Internal memory free"></Overload>
|
<Overload retVal="void" descr="Internal memory free"></Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
<!-- Set custom callbacks -->
|
<!-- File system management functions -->
|
||||||
<!-- WARNING: Callbacks setup is intended for advanced users -->
|
|
||||||
<KeyWord name="SetTraceLogCallback" func="yes">
|
|
||||||
<Overload retVal="void" descr="Set custom trace log">
|
|
||||||
<Param name="TraceLogCallback callback" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="SetLoadFileDataCallback" func="yes">
|
|
||||||
<Overload retVal="void" descr="Set custom file binary data loader">
|
|
||||||
<Param name="LoadFileDataCallback callback" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="SetSaveFileDataCallback" func="yes">
|
|
||||||
<Overload retVal="void" descr="Set custom file binary data saver">
|
|
||||||
<Param name="SaveFileDataCallback callback" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="SetLoadFileTextCallback" func="yes">
|
|
||||||
<Overload retVal="void" descr="Set custom file text data loader">
|
|
||||||
<Param name="LoadFileTextCallback callback" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="SetSaveFileTextCallback" func="yes">
|
|
||||||
<Overload retVal="void" descr="Set custom file text data saver">
|
|
||||||
<Param name="SaveFileTextCallback callback" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
|
|
||||||
<!-- Files management functions -->
|
|
||||||
<KeyWord name="char *LoadFileData" func="yes">
|
<KeyWord name="char *LoadFileData" func="yes">
|
||||||
<Overload retVal="unsigned" descr="Load file data as byte array (read)">
|
<Overload retVal="unsigned" descr="Load file data as byte array (read)">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
|
|
@ -588,12 +566,69 @@
|
||||||
<KeyWord name="SaveFileText" func="yes">
|
<KeyWord name="SaveFileText" func="yes">
|
||||||
<Overload retVal="bool" descr="Save text data to file (write), string must be '\0' terminated, returns true on success">
|
<Overload retVal="bool" descr="Save text data to file (write), string must be '\0' terminated, returns true on success">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
<Param name="char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<!-------------------------------------------------------------------- -->
|
|
||||||
|
|
||||||
<!-- File system functions -->
|
<!-- File access custom callbacks -->
|
||||||
|
<!-- WARNING: Callbacks setup is intended for advanced users -->
|
||||||
|
<KeyWord name="SetLoadFileDataCallback" func="yes">
|
||||||
|
<Overload retVal="void" descr="Set custom file binary data loader">
|
||||||
|
<Param name="LoadFileDataCallback callback" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="SetSaveFileDataCallback" func="yes">
|
||||||
|
<Overload retVal="void" descr="Set custom file binary data saver">
|
||||||
|
<Param name="SaveFileDataCallback callback" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="SetLoadFileTextCallback" func="yes">
|
||||||
|
<Overload retVal="void" descr="Set custom file text data loader">
|
||||||
|
<Param name="LoadFileTextCallback callback" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="SetSaveFileTextCallback" func="yes">
|
||||||
|
<Overload retVal="void" descr="Set custom file text data saver">
|
||||||
|
<Param name="SaveFileTextCallback callback" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
|
||||||
|
<KeyWord name="FileRename" func="yes">
|
||||||
|
<Overload retVal="int" descr="Rename file (if exists)">
|
||||||
|
<Param name="const char *fileName" />
|
||||||
|
<Param name="const char *fileRename" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="FileRemove" func="yes">
|
||||||
|
<Overload retVal="int" descr="Remove file (if exists)">
|
||||||
|
<Param name="const char *fileName" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="FileCopy" func="yes">
|
||||||
|
<Overload retVal="int" descr="Copy file from one path to another, dstPath created if it doesn't exist">
|
||||||
|
<Param name="const char *srcPath" />
|
||||||
|
<Param name="const char *dstPath" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="FileMove" func="yes">
|
||||||
|
<Overload retVal="int" descr="Move file from one directory to another, dstPath created if it doesn't exist">
|
||||||
|
<Param name="const char *srcPath" />
|
||||||
|
<Param name="const char *dstPath" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="FileTextReplace" func="yes">
|
||||||
|
<Overload retVal="int" descr="Replace text in an existing file">
|
||||||
|
<Param name="const char *fileName" />
|
||||||
|
<Param name="const char *search" />
|
||||||
|
<Param name="const char *replacement" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="FileTextFindIndex" func="yes">
|
||||||
|
<Overload retVal="int" descr="Find text in existing file">
|
||||||
|
<Param name="const char *fileName" />
|
||||||
|
<Param name="const char *search" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="FileExists" func="yes">
|
<KeyWord name="FileExists" func="yes">
|
||||||
<Overload retVal="bool" descr="Check if file exists">
|
<Overload retVal="bool" descr="Check if file exists">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
|
|
@ -605,7 +640,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="IsFileExtension" func="yes">
|
<KeyWord name="IsFileExtension" func="yes">
|
||||||
<Overload retVal="bool" descr="Check file extension (including point: .png, .wav)">
|
<Overload retVal="bool" descr="Check file extension (recommended include point: .png, .wav)">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
<Param name="const char *ext" />
|
<Param name="const char *ext" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -615,6 +650,11 @@
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="GetFileModTime" func="yes">
|
||||||
|
<Overload retVal="long" descr="Get file modification time (last write time)">
|
||||||
|
<Param name="const char *fileName" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="GetFileExtension" func="yes">
|
<KeyWord name="GetFileExtension" func="yes">
|
||||||
<Overload retVal="const char" descr="Get pointer to extension for a filename string (includes dot: '.png')">
|
<Overload retVal="const char" descr="Get pointer to extension for a filename string (includes dot: '.png')">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
|
|
@ -653,7 +693,7 @@
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="ChangeDirectory" func="yes">
|
<KeyWord name="ChangeDirectory" func="yes">
|
||||||
<Overload retVal="bool" descr="Change working directory, return true on success">
|
<Overload retVal="bool" descr="Change working directory, return true on success">
|
||||||
<Param name="const char *dir" />
|
<Param name="const char *dirPath" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="IsPathFile" func="yes">
|
<KeyWord name="IsPathFile" func="yes">
|
||||||
|
|
@ -667,12 +707,12 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="LoadDirectoryFiles" func="yes">
|
<KeyWord name="LoadDirectoryFiles" func="yes">
|
||||||
<Overload retVal="FilePathList" descr="Load directory filepaths">
|
<Overload retVal="FilePathList" descr="Load directory filepaths, files and directories, no subdirs scan">
|
||||||
<Param name="const char *dirPath" />
|
<Param name="const char *dirPath" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="LoadDirectoryFilesEx" func="yes">
|
<KeyWord name="LoadDirectoryFilesEx" func="yes">
|
||||||
<Overload retVal="FilePathList" descr="Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
|
<Overload retVal="FilePathList" descr="Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"">
|
||||||
<Param name="const char *basePath" />
|
<Param name="const char *basePath" />
|
||||||
<Param name="const char *filter" />
|
<Param name="const char *filter" />
|
||||||
<Param name="bool scanSubdirs" />
|
<Param name="bool scanSubdirs" />
|
||||||
|
|
@ -694,9 +734,16 @@
|
||||||
<Param name="FilePathList files" />
|
<Param name="FilePathList files" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="GetFileModTime" func="yes">
|
<KeyWord name="int GetDirectoryFileCount" func="yes">
|
||||||
<Overload retVal="long" descr="Get file modification time (last write time)">
|
<Overload retVal="unsigned" descr="Get the file count in a directory">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *dirPath" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="int GetDirectoryFileCountEx" func="yes">
|
||||||
|
<Overload retVal="unsigned" descr="Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
|
||||||
|
<Param name="const char *basePath" />
|
||||||
|
<Param name="const char *filter" />
|
||||||
|
<Param name="bool scanSubdirs" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
|
|
@ -716,15 +763,15 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="EncodeDataBase64" func="yes">
|
<KeyWord name="EncodeDataBase64" func="yes">
|
||||||
<Overload retVal="char" descr="Encode data to Base64 string, memory must be MemFree()">
|
<Overload retVal="char" descr="Encode data to Base64 string (includes NULL terminator), memory must be MemFree()">
|
||||||
<Param name="const unsigned char" />
|
<Param name="const unsigned char" />
|
||||||
<Param name="int dataSize" />
|
<Param name="int dataSize" />
|
||||||
<Param name="int *outputSize" />
|
<Param name="int *outputSize" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="char *DecodeDataBase64" func="yes">
|
<KeyWord name="char *DecodeDataBase64" func="yes">
|
||||||
<Overload retVal="unsigned" descr="Decode Base64 string data, memory must be MemFree()">
|
<Overload retVal="unsigned" descr="Decode Base64 string (expected NULL terminated), memory must be MemFree()">
|
||||||
<Param name="const unsigned char" />
|
<Param name="const char *text" />
|
||||||
<Param name="int *outputSize" />
|
<Param name="int *outputSize" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
@ -746,7 +793,12 @@
|
||||||
<Param name="int dataSize" />
|
<Param name="int dataSize" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="int *ComputeSHA256" func="yes">
|
||||||
|
<Overload retVal="unsigned" descr="Compute SHA256 hash code, returns static int[8] (32 bytes)">
|
||||||
|
<Param name="unsigned char *data" />
|
||||||
|
<Param name="int dataSize" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
|
||||||
<!-- Automation events functionality -->
|
<!-- Automation events functionality -->
|
||||||
<KeyWord name="LoadAutomationEventList" func="yes">
|
<KeyWord name="LoadAutomationEventList" func="yes">
|
||||||
|
|
@ -823,6 +875,11 @@
|
||||||
<KeyWord name="GetCharPressed" func="yes">
|
<KeyWord name="GetCharPressed" func="yes">
|
||||||
<Overload retVal="int" descr="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty"></Overload>
|
<Overload retVal="int" descr="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty"></Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="GetKeyName" func="yes">
|
||||||
|
<Overload retVal="const char" descr="Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)">
|
||||||
|
<Param name="int key" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="SetExitKey" func="yes">
|
<KeyWord name="SetExitKey" func="yes">
|
||||||
<Overload retVal="void" descr="Set a custom key to exit program (default is ESC)">
|
<Overload retVal="void" descr="Set a custom key to exit program (default is ESC)">
|
||||||
<Param name="int key" />
|
<Param name="int key" />
|
||||||
|
|
@ -868,12 +925,12 @@
|
||||||
<Overload retVal="int" descr="Get the last gamepad button pressed"></Overload>
|
<Overload retVal="int" descr="Get the last gamepad button pressed"></Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="GetGamepadAxisCount" func="yes">
|
<KeyWord name="GetGamepadAxisCount" func="yes">
|
||||||
<Overload retVal="int" descr="Get gamepad axis count for a gamepad">
|
<Overload retVal="int" descr="Get axis count for a gamepad">
|
||||||
<Param name="int gamepad" />
|
<Param name="int gamepad" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="GetGamepadAxisMovement" func="yes">
|
<KeyWord name="GetGamepadAxisMovement" func="yes">
|
||||||
<Overload retVal="float" descr="Get axis movement value for a gamepad axis">
|
<Overload retVal="float" descr="Get movement value for a gamepad axis">
|
||||||
<Param name="int gamepad" />
|
<Param name="int gamepad" />
|
||||||
<Param name="int axis" />
|
<Param name="int axis" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -1098,6 +1155,15 @@
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="DrawLineDashed" func="yes">
|
||||||
|
<Overload retVal="void" descr="Draw a dashed line">
|
||||||
|
<Param name="Vector2 startPos" />
|
||||||
|
<Param name="Vector2 endPos" />
|
||||||
|
<Param name="int dashSize" />
|
||||||
|
<Param name="int spaceSize" />
|
||||||
|
<Param name="Color color" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="DrawCircle" func="yes">
|
<KeyWord name="DrawCircle" func="yes">
|
||||||
<Overload retVal="void" descr="Draw a color-filled circle">
|
<Overload retVal="void" descr="Draw a color-filled circle">
|
||||||
<Param name="int centerX" />
|
<Param name="int centerX" />
|
||||||
|
|
@ -1106,6 +1172,21 @@
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="DrawCircleV" func="yes">
|
||||||
|
<Overload retVal="void" descr="Draw a color-filled circle (Vector version)">
|
||||||
|
<Param name="Vector2 center" />
|
||||||
|
<Param name="float radius" />
|
||||||
|
<Param name="Color color" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="DrawCircleGradient" func="yes">
|
||||||
|
<Overload retVal="void" descr="Draw a gradient-filled circle">
|
||||||
|
<Param name="Vector2 center" />
|
||||||
|
<Param name="float radius" />
|
||||||
|
<Param name="Color inner" />
|
||||||
|
<Param name="Color outer" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="DrawCircleSector" func="yes">
|
<KeyWord name="DrawCircleSector" func="yes">
|
||||||
<Overload retVal="void" descr="Draw a piece of a circle">
|
<Overload retVal="void" descr="Draw a piece of a circle">
|
||||||
<Param name="Vector2 center" />
|
<Param name="Vector2 center" />
|
||||||
|
|
@ -1126,22 +1207,6 @@
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="DrawCircleGradient" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a gradient-filled circle">
|
|
||||||
<Param name="int centerX" />
|
|
||||||
<Param name="int centerY" />
|
|
||||||
<Param name="float radius" />
|
|
||||||
<Param name="Color inner" />
|
|
||||||
<Param name="Color outer" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawCircleV" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a color-filled circle (Vector version)">
|
|
||||||
<Param name="Vector2 center" />
|
|
||||||
<Param name="float radius" />
|
|
||||||
<Param name="Color color" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawCircleLines" func="yes">
|
<KeyWord name="DrawCircleLines" func="yes">
|
||||||
<Overload retVal="void" descr="Draw circle outline">
|
<Overload retVal="void" descr="Draw circle outline">
|
||||||
<Param name="int centerX" />
|
<Param name="int centerX" />
|
||||||
|
|
@ -1166,6 +1231,14 @@
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="DrawEllipseV" func="yes">
|
||||||
|
<Overload retVal="void" descr="Draw ellipse (Vector version)">
|
||||||
|
<Param name="Vector2 center" />
|
||||||
|
<Param name="float radiusH" />
|
||||||
|
<Param name="float radiusV" />
|
||||||
|
<Param name="Color color" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="DrawEllipseLines" func="yes">
|
<KeyWord name="DrawEllipseLines" func="yes">
|
||||||
<Overload retVal="void" descr="Draw ellipse outline">
|
<Overload retVal="void" descr="Draw ellipse outline">
|
||||||
<Param name="int centerX" />
|
<Param name="int centerX" />
|
||||||
|
|
@ -1175,6 +1248,14 @@
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="DrawEllipseLinesV" func="yes">
|
||||||
|
<Overload retVal="void" descr="Draw ellipse outline (Vector version)">
|
||||||
|
<Param name="Vector2 center" />
|
||||||
|
<Param name="float radiusH" />
|
||||||
|
<Param name="float radiusV" />
|
||||||
|
<Param name="Color color" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="DrawRing" func="yes">
|
<KeyWord name="DrawRing" func="yes">
|
||||||
<Overload retVal="void" descr="Draw ring">
|
<Overload retVal="void" descr="Draw ring">
|
||||||
<Param name="Vector2 center" />
|
<Param name="Vector2 center" />
|
||||||
|
|
@ -1252,8 +1333,8 @@
|
||||||
<Param name="Rectangle rec" />
|
<Param name="Rectangle rec" />
|
||||||
<Param name="Color topLeft" />
|
<Param name="Color topLeft" />
|
||||||
<Param name="Color bottomLeft" />
|
<Param name="Color bottomLeft" />
|
||||||
<Param name="Color topRight" />
|
|
||||||
<Param name="Color bottomRight" />
|
<Param name="Color bottomRight" />
|
||||||
|
<Param name="Color topRight" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="DrawRectangleLines" func="yes">
|
<KeyWord name="DrawRectangleLines" func="yes">
|
||||||
|
|
@ -1637,7 +1718,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="char *ExportImageToMemory" func="yes">
|
<KeyWord name="char *ExportImageToMemory" func="yes">
|
||||||
<Overload retVal="unsigned" descr="Export image to memory buffer">
|
<Overload retVal="unsigned" descr="Export image to memory buffer, memory must be MemFree()">
|
||||||
<Param name="Image image" />
|
<Param name="Image image" />
|
||||||
<Param name="const char *fileType" />
|
<Param name="const char *fileType" />
|
||||||
<Param name="int *fileSize" />
|
<Param name="int *fileSize" />
|
||||||
|
|
@ -2099,7 +2180,7 @@
|
||||||
<KeyWord name="ImageDrawTriangleFan" func="yes">
|
<KeyWord name="ImageDrawTriangleFan" func="yes">
|
||||||
<Overload retVal="void" descr="Draw a triangle fan defined by points within an image (first vertex is the center)">
|
<Overload retVal="void" descr="Draw a triangle fan defined by points within an image (first vertex is the center)">
|
||||||
<Param name="Image *dst" />
|
<Param name="Image *dst" />
|
||||||
<Param name="Vector2 *points" />
|
<Param name="const Vector2 *points" />
|
||||||
<Param name="int pointCount" />
|
<Param name="int pointCount" />
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -2107,7 +2188,7 @@
|
||||||
<KeyWord name="ImageDrawTriangleStrip" func="yes">
|
<KeyWord name="ImageDrawTriangleStrip" func="yes">
|
||||||
<Overload retVal="void" descr="Draw a triangle strip defined by points within an image">
|
<Overload retVal="void" descr="Draw a triangle strip defined by points within an image">
|
||||||
<Param name="Image *dst" />
|
<Param name="Image *dst" />
|
||||||
<Param name="Vector2 *points" />
|
<Param name="const Vector2 *points" />
|
||||||
<Param name="int pointCount" />
|
<Param name="int pointCount" />
|
||||||
<Param name="Color color" />
|
<Param name="Color color" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -2188,13 +2269,13 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UpdateTexture" func="yes">
|
<KeyWord name="UpdateTexture" func="yes">
|
||||||
<Overload retVal="void" descr="Update GPU texture with new data">
|
<Overload retVal="void" descr="Update GPU texture with new data (pixels should be able to fill texture)">
|
||||||
<Param name="Texture2D texture" />
|
<Param name="Texture2D texture" />
|
||||||
<Param name="const void *pixels" />
|
<Param name="const void *pixels" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UpdateTextureRec" func="yes">
|
<KeyWord name="UpdateTextureRec" func="yes">
|
||||||
<Overload retVal="void" descr="Update GPU texture rectangle with new data">
|
<Overload retVal="void" descr="Update GPU texture rectangle with new data (pixels and rec should fit in texture)">
|
||||||
<Param name="Texture2D texture" />
|
<Param name="Texture2D texture" />
|
||||||
<Param name="Rectangle rec" />
|
<Param name="Rectangle rec" />
|
||||||
<Param name="const void *pixels" />
|
<Param name="const void *pixels" />
|
||||||
|
|
@ -2388,7 +2469,7 @@
|
||||||
<Overload retVal="Font" descr="Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height">
|
<Overload retVal="Font" descr="Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height">
|
||||||
<Param name="const char *fileName" />
|
<Param name="const char *fileName" />
|
||||||
<Param name="int fontSize" />
|
<Param name="int fontSize" />
|
||||||
<Param name="int *codepoints" />
|
<Param name="const int *codepoints" />
|
||||||
<Param name="int codepointCount" />
|
<Param name="int codepointCount" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
@ -2405,7 +2486,7 @@
|
||||||
<Param name="const unsigned char" />
|
<Param name="const unsigned char" />
|
||||||
<Param name="int dataSize" />
|
<Param name="int dataSize" />
|
||||||
<Param name="int fontSize" />
|
<Param name="int fontSize" />
|
||||||
<Param name="int *codepoints" />
|
<Param name="const int *codepoints" />
|
||||||
<Param name="int codepointCount" />
|
<Param name="int codepointCount" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
@ -2419,9 +2500,10 @@
|
||||||
<Param name="const unsigned char" />
|
<Param name="const unsigned char" />
|
||||||
<Param name="int dataSize" />
|
<Param name="int dataSize" />
|
||||||
<Param name="int fontSize" />
|
<Param name="int fontSize" />
|
||||||
<Param name="int *codepoints" />
|
<Param name="const int *codepoints" />
|
||||||
<Param name="int codepointCount" />
|
<Param name="int codepointCount" />
|
||||||
<Param name="int type" />
|
<Param name="int type" />
|
||||||
|
<Param name="int *glyphCount" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="GenImageFontAtlas" func="yes">
|
<KeyWord name="GenImageFontAtlas" func="yes">
|
||||||
|
|
@ -2531,6 +2613,15 @@
|
||||||
<Param name="float spacing" />
|
<Param name="float spacing" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
<KeyWord name="MeasureTextCodepoints" func="yes">
|
||||||
|
<Overload retVal="Vector2" descr="Measure string size for an existing array of codepoints for Font">
|
||||||
|
<Param name="Font font" />
|
||||||
|
<Param name="const int *codepoints" />
|
||||||
|
<Param name="int length" />
|
||||||
|
<Param name="float fontSize" />
|
||||||
|
<Param name="float spacing" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="GetGlyphIndex" func="yes">
|
<KeyWord name="GetGlyphIndex" func="yes">
|
||||||
<Overload retVal="int" descr="Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found">
|
<Overload retVal="int" descr="Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found">
|
||||||
<Param name="Font font" />
|
<Param name="Font font" />
|
||||||
|
|
@ -2604,7 +2695,20 @@
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
<!-- Text strings management functions (no UTF-8 strings, only byte chars) -->
|
<!-- Text strings management functions (no UTF-8 strings, only byte chars) -->
|
||||||
<!-- NOTE: Some strings allocate memory internally for returned strings, just be careful! -->
|
<!-- WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use -->
|
||||||
|
<!-- WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree() -->
|
||||||
|
<KeyWord name="LoadTextLines" func="yes">
|
||||||
|
<Overload retVal="char" descr="Load text as separate lines ('\n')">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="int *count" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="UnloadTextLines" func="yes">
|
||||||
|
<Overload retVal="void" descr="Unload text lines">
|
||||||
|
<Param name="char **text" />
|
||||||
|
<Param name="int lineCount" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
<KeyWord name="TextCopy" func="yes">
|
<KeyWord name="TextCopy" func="yes">
|
||||||
<Overload retVal="int" descr="Copy one string to another, returns bytes copied">
|
<Overload retVal="int" descr="Copy one string to another, returns bytes copied">
|
||||||
<Param name="char *dst" />
|
<Param name="char *dst" />
|
||||||
|
|
@ -2635,80 +2739,121 @@
|
||||||
<Param name="int length" />
|
<Param name="int length" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextReplace" func="yes">
|
<KeyWord name="TextRemoveSpaces" func="yes">
|
||||||
<Overload retVal="char" descr="Replace text string (WARNING: memory must be freed!)">
|
<Overload retVal="const char" descr="Remove text spaces, concat words">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
<Param name="const char *replace" />
|
</Overload>
|
||||||
<Param name="const char *by" />
|
</KeyWord>
|
||||||
|
<KeyWord name="GetTextBetween" func="yes">
|
||||||
|
<Overload retVal="char" descr="Get text between two strings">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *begin" />
|
||||||
|
<Param name="const char *end" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="TextReplace" func="yes">
|
||||||
|
<Overload retVal="char" descr="Replace text string with new string">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *search" />
|
||||||
|
<Param name="const char *replacement" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="TextReplaceAlloc" func="yes">
|
||||||
|
<Overload retVal="char" descr="Replace text string with new string, memory must be MemFree()">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *search" />
|
||||||
|
<Param name="const char *replacement" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="TextReplaceBetween" func="yes">
|
||||||
|
<Overload retVal="char" descr="Replace text between two specific strings">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *begin" />
|
||||||
|
<Param name="const char *end" />
|
||||||
|
<Param name="const char *replacement" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="TextReplaceBetweenAlloc" func="yes">
|
||||||
|
<Overload retVal="char" descr="Replace text between two specific strings, memory must be MemFree()">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *begin" />
|
||||||
|
<Param name="const char *end" />
|
||||||
|
<Param name="const char *replacement" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextInsert" func="yes">
|
<KeyWord name="TextInsert" func="yes">
|
||||||
<Overload retVal="char" descr="Insert text in a position (WARNING: memory must be freed!)">
|
<Overload retVal="char" descr="Insert text in a defined byte position">
|
||||||
|
<Param name="const char *text" />
|
||||||
|
<Param name="const char *insert" />
|
||||||
|
<Param name="int position" />
|
||||||
|
</Overload>
|
||||||
|
</KeyWord>
|
||||||
|
<KeyWord name="TextInsertAlloc" func="yes">
|
||||||
|
<Overload retVal="char" descr="Insert text in a defined byte position, memory must be MemFree()">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
<Param name="const char *insert" />
|
<Param name="const char *insert" />
|
||||||
<Param name="int position" />
|
<Param name="int position" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextJoin" func="yes">
|
<KeyWord name="TextJoin" func="yes">
|
||||||
<Overload retVal="const char" descr="Join text strings with delimiter">
|
<Overload retVal="char" descr="Join text strings with delimiter">
|
||||||
<Param name="const char **textList" />
|
<Param name="char **textList" />
|
||||||
<Param name="int count" />
|
<Param name="int count" />
|
||||||
<Param name="const char *delimiter" />
|
<Param name="const char *delimiter" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextSplit" func="yes">
|
<KeyWord name="TextSplit" func="yes">
|
||||||
<Overload retVal="const char" descr="Split text into multiple strings">
|
<Overload retVal="char" descr="Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
<Param name="char delimiter" />
|
<Param name="char delimiter" />
|
||||||
<Param name="int *count" />
|
<Param name="int *count" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextAppend" func="yes">
|
<KeyWord name="TextAppend" func="yes">
|
||||||
<Overload retVal="void" descr="Append text at specific position and move cursor!">
|
<Overload retVal="void" descr="Append text at specific position and move cursor">
|
||||||
<Param name="char *text" />
|
<Param name="char *text" />
|
||||||
<Param name="const char *append" />
|
<Param name="const char *append" />
|
||||||
<Param name="int *position" />
|
<Param name="int *position" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextFindIndex" func="yes">
|
<KeyWord name="TextFindIndex" func="yes">
|
||||||
<Overload retVal="int" descr="Find first text occurrence within a string">
|
<Overload retVal="int" descr="Find first text occurrence within a string, -1 if not found">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
<Param name="const char *find" />
|
<Param name="const char *search" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToUpper" func="yes">
|
<KeyWord name="TextToUpper" func="yes">
|
||||||
<Overload retVal="const char" descr="Get upper case version of provided string">
|
<Overload retVal="char" descr="Get upper case version of provided string">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToLower" func="yes">
|
<KeyWord name="TextToLower" func="yes">
|
||||||
<Overload retVal="const char" descr="Get lower case version of provided string">
|
<Overload retVal="char" descr="Get lower case version of provided string">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToPascal" func="yes">
|
<KeyWord name="TextToPascal" func="yes">
|
||||||
<Overload retVal="const char" descr="Get Pascal case notation version of provided string">
|
<Overload retVal="char" descr="Get Pascal case notation version of provided string">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToSnake" func="yes">
|
<KeyWord name="TextToSnake" func="yes">
|
||||||
<Overload retVal="const char" descr="Get Snake case notation version of provided string">
|
<Overload retVal="char" descr="Get Snake case notation version of provided string">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToCamel" func="yes">
|
<KeyWord name="TextToCamel" func="yes">
|
||||||
<Overload retVal="const char" descr="Get Camel case notation version of provided string">
|
<Overload retVal="char" descr="Get Camel case notation version of provided string">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
<KeyWord name="TextToInteger" func="yes">
|
<KeyWord name="TextToInteger" func="yes">
|
||||||
<Overload retVal="int" descr="Get integer value from text (negative values not supported)">
|
<Overload retVal="int" descr="Get integer value from text">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="TextToFloat" func="yes">
|
<KeyWord name="TextToFloat" func="yes">
|
||||||
<Overload retVal="float" descr="Get float value from text (negative values not supported)">
|
<Overload retVal="float" descr="Get float value from text">
|
||||||
<Param name="const char *text" />
|
<Param name="const char *text" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
@ -2960,24 +3105,6 @@
|
||||||
<Param name="Color tint" />
|
<Param name="Color tint" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="DrawModelPoints" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a model as points">
|
|
||||||
<Param name="Model model" />
|
|
||||||
<Param name="Vector3 position" />
|
|
||||||
<Param name="float scale" />
|
|
||||||
<Param name="Color tint" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawModelPointsEx" func="yes">
|
|
||||||
<Overload retVal="void" descr="Draw a model as points with extended parameters">
|
|
||||||
<Param name="Model model" />
|
|
||||||
<Param name="Vector3 position" />
|
|
||||||
<Param name="Vector3 rotationAxis" />
|
|
||||||
<Param name="float rotationAngle" />
|
|
||||||
<Param name="Vector3 scale" />
|
|
||||||
<Param name="Color tint" />
|
|
||||||
</Overload>
|
|
||||||
</KeyWord>
|
|
||||||
<KeyWord name="DrawBoundingBox" func="yes">
|
<KeyWord name="DrawBoundingBox" func="yes">
|
||||||
<Overload retVal="void" descr="Draw bounding box (wires)">
|
<Overload retVal="void" descr="Draw bounding box (wires)">
|
||||||
<Param name="BoundingBox box" />
|
<Param name="BoundingBox box" />
|
||||||
|
|
@ -3013,7 +3140,7 @@
|
||||||
<Param name="Vector2 size" />
|
<Param name="Vector2 size" />
|
||||||
<Param name="Vector2 origin" />
|
<Param name="Vector2 origin" />
|
||||||
<Param name="float rotation" />
|
<Param name="float rotation" />
|
||||||
<Param name="°ñ_)% " />
|
<Param name="Color tint" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
|
|
@ -3198,22 +3325,20 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UpdateModelAnimation" func="yes">
|
<KeyWord name="UpdateModelAnimation" func="yes">
|
||||||
<Overload retVal="void" descr="Update model animation pose (CPU)">
|
<Overload retVal="void" descr="Update model animation pose (vertex buffers and bone matrices)">
|
||||||
<Param name="Model model" />
|
<Param name="Model model" />
|
||||||
<Param name="ModelAnimation anim" />
|
<Param name="ModelAnimation anim" />
|
||||||
<Param name="int frame" />
|
<Param name="float frame" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UpdateModelAnimationBones" func="yes">
|
<KeyWord name="UpdateModelAnimationEx" func="yes">
|
||||||
<Overload retVal="void" descr="Update model animation mesh bone matrices (GPU skinning)">
|
<Overload retVal="void" descr="Update model animation pose, blending two animations">
|
||||||
<Param name="Model model" />
|
<Param name="Model model" />
|
||||||
<Param name="ModelAnimation anim" />
|
<Param name="ModelAnimation animA" />
|
||||||
<Param name="int frame" />
|
<Param name="float frameA" />
|
||||||
</Overload>
|
<Param name="ModelAnimation animB" />
|
||||||
</KeyWord>
|
<Param name="float frameB" />
|
||||||
<KeyWord name="UnloadModelAnimation" func="yes">
|
<Param name="float blend" />
|
||||||
<Overload retVal="void" descr="Unload animation data">
|
|
||||||
<Param name="ModelAnimation anim" />
|
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UnloadModelAnimations" func="yes">
|
<KeyWord name="UnloadModelAnimations" func="yes">
|
||||||
|
|
@ -3351,7 +3476,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="UpdateSound" func="yes">
|
<KeyWord name="UpdateSound" func="yes">
|
||||||
<Overload retVal="void" descr="Update sound buffer with new data">
|
<Overload retVal="void" descr="Update sound buffer with new data (default data format: 32 bit float, stereo)">
|
||||||
<Param name="Sound sound" />
|
<Param name="Sound sound" />
|
||||||
<Param name="const void *data" />
|
<Param name="const void *data" />
|
||||||
<Param name="int sampleCount" />
|
<Param name="int sampleCount" />
|
||||||
|
|
@ -3424,7 +3549,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="SetSoundPan" func="yes">
|
<KeyWord name="SetSoundPan" func="yes">
|
||||||
<Overload retVal="void" descr="Set pan for a sound (0.5 is center)">
|
<Overload retVal="void" descr="Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)">
|
||||||
<Param name="Sound sound" />
|
<Param name="Sound sound" />
|
||||||
<Param name="float pan" />
|
<Param name="float pan" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -3532,7 +3657,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="SetMusicPan" func="yes">
|
<KeyWord name="SetMusicPan" func="yes">
|
||||||
<Overload retVal="void" descr="Set pan for a music (0.5 is center)">
|
<Overload retVal="void" descr="Set pan for a music (-1.0 left, 0.0 center, 1.0 right)">
|
||||||
<Param name="Music music" />
|
<Param name="Music music" />
|
||||||
<Param name="float pan" />
|
<Param name="float pan" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -3616,7 +3741,7 @@
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
<KeyWord name="SetAudioStreamPan" func="yes">
|
<KeyWord name="SetAudioStreamPan" func="yes">
|
||||||
<Overload retVal="void" descr="Set pan for audio stream (0.5 is centered)">
|
<Overload retVal="void" descr="Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)">
|
||||||
<Param name="AudioStream stream" />
|
<Param name="AudioStream stream" />
|
||||||
<Param name="float pan" />
|
<Param name="float pan" />
|
||||||
</Overload>
|
</Overload>
|
||||||
|
|
@ -3656,5 +3781,3 @@
|
||||||
<Param name="AudioCallback processor" />
|
<Param name="AudioCallback processor" />
|
||||||
</Overload>
|
</Overload>
|
||||||
</KeyWord>
|
</KeyWord>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window
|
||||||
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
|
RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
|
||||||
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
|
||||||
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
RLAPI const char *GetClipboardText(void); // Get clipboard text content
|
||||||
RLAPI Image GetClipboardImage(void); // Get clipboard image
|
RLAPI Image GetClipboardImage(void); // Get clipboard image content
|
||||||
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Ge
|
||||||
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
|
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
|
||||||
RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector
|
RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector
|
||||||
RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
|
RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d)
|
RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d)
|
||||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
// Screen-space-related functions
|
// Screen-space-related functions
|
||||||
|
|
@ -133,37 +133,43 @@ RLAPI void TakeScreenshot(const char *fileName); // Takes a scr
|
||||||
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
|
||||||
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
|
||||||
|
|
||||||
// NOTE: Following functions implemented in module [utils]
|
// Logging system
|
||||||
//------------------------------------------------------------------
|
|
||||||
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
|
||||||
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
|
||||||
|
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
|
||||||
|
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
||||||
|
|
||||||
|
// Memory management, using internal allocators
|
||||||
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
|
||||||
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
|
||||||
RLAPI void MemFree(void *ptr); // Internal memory free
|
RLAPI void MemFree(void *ptr); // Internal memory free
|
||||||
|
|
||||||
// Set custom callbacks
|
// File system management functions
|
||||||
// WARNING: Callbacks setup is intended for advanced users
|
|
||||||
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
|
|
||||||
RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
|
|
||||||
RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
|
|
||||||
RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
|
|
||||||
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
|
||||||
|
|
||||||
// Files management functions
|
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), 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 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 access custom callbacks
|
||||||
|
// WARNING: Callbacks setup is intended for advanced users
|
||||||
|
RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
|
||||||
|
RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
|
||||||
|
RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
|
||||||
|
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
|
||||||
|
|
||||||
|
RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists)
|
||||||
|
RLAPI int FileRemove(const char *fileName); // Remove file (if exists)
|
||||||
|
RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist
|
||||||
|
RLAPI int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist
|
||||||
|
RLAPI int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file
|
||||||
|
RLAPI int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file
|
||||||
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
RLAPI bool FileExists(const char *fileName); // Check if file exists
|
||||||
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
|
||||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
|
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (recommended include point: .png, .wav)
|
||||||
RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
|
RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
|
||||||
|
RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
|
||||||
RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
|
RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
|
||||||
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
|
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
|
||||||
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
|
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
|
||||||
|
|
@ -172,26 +178,27 @@ RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previou
|
||||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
|
||||||
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
|
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
|
||||||
RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
|
RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
|
||||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
|
||||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"
|
||||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||||
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
|
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
|
||||||
RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
|
RLAPI unsigned int GetDirectoryFileCount(const char *dirPath); // Get the file count in a directory
|
||||||
|
RLAPI unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, bool scanSubdirs); // Get the file count in a directory with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
||||||
|
|
||||||
// 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)
|
||||||
|
RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes)
|
||||||
|
|
||||||
// Automation events functionality
|
// Automation events functionality
|
||||||
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||||
|
|
@ -215,8 +222,8 @@ RLAPI bool IsKeyReleased(int key); // Check if a key
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||||
|
RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
|
||||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string "q" for KEY_A on an AZERTY keyboard)
|
|
||||||
|
|
||||||
// Input-related functions: gamepads
|
// Input-related functions: gamepads
|
||||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||||
|
|
@ -226,8 +233,8 @@ RLAPI bool IsGamepadButtonDown(int gamepad, int button);
|
||||||
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)
|
||||||
|
|
||||||
|
|
@ -290,15 +297,18 @@ RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);
|
||||||
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
|
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
|
||||||
RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
|
RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
|
||||||
|
RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
|
RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
||||||
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
|
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
|
||||||
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
|
||||||
|
|
@ -307,7 +317,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
|
||||||
|
|
@ -369,7 +379,7 @@ RLAPI Image LoadImageFromScreen(void);
|
||||||
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree()
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
|
|
@ -456,8 +466,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
|
||||||
|
|
@ -498,11 +508,11 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
|
||||||
// Font loading/unloading functions
|
// Font loading/unloading functions
|
||||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
||||||
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
|
RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
|
||||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
|
||||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||||
|
|
@ -520,6 +530,7 @@ RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCou
|
||||||
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
|
RLAPI Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, float fontSize, float spacing); // Measure string size for an existing array of codepoints for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
|
||||||
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
|
@ -536,26 +547,34 @@ RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get p
|
||||||
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||||
|
|
||||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||||
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
||||||
|
// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree()
|
||||||
|
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||||
|
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||||
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
||||||
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
||||||
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
|
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
|
||||||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||||
RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!)
|
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||||
RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||||
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
|
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||||
RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
|
RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||||
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
|
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position
|
||||||
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||||
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||||
RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
|
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
||||||
RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
|
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
||||||
|
RLAPI int TextFindIndex(const char *text, const char *search); // Find first text occurrence within a string, -1 if not found
|
||||||
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
|
RLAPI char *TextToUpper(const char *text); // Get upper case version of provided string
|
||||||
RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported)
|
RLAPI char *TextToLower(const char *text); // Get lower case version of provided string
|
||||||
|
RLAPI char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
||||||
|
RLAPI char *TextToSnake(const char *text); // Get Snake case notation version of provided string
|
||||||
|
RLAPI char *TextToCamel(const char *text); // Get Camel case notation version of provided string
|
||||||
|
RLAPI int TextToInteger(const char *text); // Get integer value from text
|
||||||
|
RLAPI float TextToFloat(const char *text); // Get float value from text
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||||
|
|
@ -600,8 +619,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
||||||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
|
||||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
|
||||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||||
|
|
@ -641,9 +658,8 @@ RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId);
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
|
||||||
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU)
|
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, float frame); // Update model animation pose (vertex buffers and bone matrices)
|
||||||
RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning)
|
RLAPI void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, ModelAnimation animB, float frameB, float blend); // Update model animation pose, blending two animations
|
||||||
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
|
|
||||||
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
|
||||||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||||
|
|
||||||
|
|
@ -677,7 +693,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 (default data format: 32 bit float, stereo)
|
||||||
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)
|
||||||
|
|
@ -692,7 +708,7 @@ RLAPI void ResumeSound(Sound sound); // Resume
|
||||||
RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||||
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center)
|
RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)
|
||||||
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
||||||
RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range
|
RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range
|
||||||
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
||||||
|
|
@ -713,7 +729,7 @@ RLAPI void ResumeMusicStream(Music music); // Resume
|
||||||
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
||||||
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (0.5 is center)
|
RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right)
|
||||||
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||||
|
|
||||||
|
|
@ -730,7 +746,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i
|
||||||
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
||||||
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||||
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
|
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||||
|
|
||||||
|
|
@ -739,4 +755,3 @@ RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processo
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo)
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo)
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ IDE | Platform(s) | Source | Example(s)
|
||||||
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
|
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
|
||||||
[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
|
[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
|
||||||
[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
|
[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
|
||||||
|
[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️
|
||||||
scripts | Windows, Linux, macOS | ✔️ | ✔️
|
scripts | Windows, Linux, macOS | ✔️ | ✔️
|
||||||
|
|
||||||
*New IDEs config files are welcome!*
|
*New IDEs config files are welcome!*
|
||||||
|
|
|
||||||
|
|
@ -1,569 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug.DLL|ARM64">
|
|
||||||
<Configuration>Debug.DLL</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug.DLL|Win32">
|
|
||||||
<Configuration>Debug.DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug.DLL|x64">
|
|
||||||
<Configuration>Debug.DLL</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|ARM64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release.DLL|ARM64">
|
|
||||||
<Configuration>Release.DLL</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release.DLL|Win32">
|
|
||||||
<Configuration>Release.DLL</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release.DLL|x64">
|
|
||||||
<Configuration>Release.DLL</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|ARM64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>web_basic_window</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
<ProjectName>web_basic_window</ProjectName>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|ARM64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|ARM64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|ARM64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|ARM64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|ARM64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|ARM64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|ARM64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|ARM64'">
|
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\others</LocalDebuggerWorkingDirectory>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
<Message>Copy Debug DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
<Message>Copy Debug DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|ARM64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
<Message>Copy Debug DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>Copy Release DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>Copy Release DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|ARM64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
|
||||||
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>Copy Release DLL to output directory</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\..\examples\others\web_basic_window.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="..\..\..\examples\examples.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\raylib\raylib.vcxproj">
|
|
||||||
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
84
projects/Zig/README.md
Normal file
84
projects/Zig/README.md
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
# Starting your raylib project with Zig (0.16.0)
|
||||||
|
|
||||||
|
## How to compile and run it
|
||||||
|
|
||||||
|
To compile the project:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the project:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compile with different optimization
|
||||||
|
|
||||||
|
To change from debug to release build you can do it with the `-Doptimze=` flag.
|
||||||
|
|
||||||
|
```
|
||||||
|
Debug
|
||||||
|
ReleaseSafe
|
||||||
|
ReleaseFast
|
||||||
|
ReleaseSmall
|
||||||
|
```
|
||||||
|
|
||||||
|
## Choose a different platform
|
||||||
|
|
||||||
|
To compile with a different platform you can use the `-Dplatform=` flag.
|
||||||
|
Here all the options:
|
||||||
|
|
||||||
|
```
|
||||||
|
glfw
|
||||||
|
rgfw
|
||||||
|
sdl
|
||||||
|
sdl2
|
||||||
|
sdl3
|
||||||
|
memory
|
||||||
|
win32
|
||||||
|
drm
|
||||||
|
android
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example the platform `sdl` and `sdl2` are not supported
|
||||||
|
|
||||||
|
Important for the android platform you also have to compile for the right target
|
||||||
|
|
||||||
|
## Compile for a different target
|
||||||
|
|
||||||
|
To compile for a different [target](https://ziglang.org/download/0.16.0/release-notes.html#Support-Table) you can use the `-Dtarget=` flag.
|
||||||
|
Not all targets are supported
|
||||||
|
|
||||||
|
## Example: Compile for web and run it
|
||||||
|
|
||||||
|
To compile for the web we use emscripten and you run it like that:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build -Dtarget=wasm32-emscripten
|
||||||
|
```
|
||||||
|
|
||||||
|
To run it we do:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build run -Dtarget=wasm32-emscripten
|
||||||
|
```
|
||||||
|
|
||||||
|
And to make a relase build we do:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
|
||||||
|
```
|
||||||
|
|
||||||
|
If we want to use rgfw for the web build we could do:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
zig build -Dplatform=rgfw -Dtarget=wasm32-emscripten -Doptimize=ReleaseFast
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compiling the Zig code? Just add `-Dzig` and try out zig ;)
|
||||||
|
|
||||||
|
## More Resources
|
||||||
|
|
||||||
|
See [Zig Build System](https://ziglang.org/learn/build-system/)
|
||||||
87
projects/Zig/build.zig
Normal file
87
projects/Zig/build.zig
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const rl = @import("raylib");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) !void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const platform = b.option(rl.PlatformBackend, "platform", "select the platform") orelse rl.PlatformBackend.glfw;
|
||||||
|
const zig = b.option(bool, "zig", "compile zig code") orelse false;
|
||||||
|
|
||||||
|
const raylib_dep = b.dependency("raylib", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.platform = platform,
|
||||||
|
});
|
||||||
|
const raylib_artifact = raylib_dep.artifact("raylib");
|
||||||
|
|
||||||
|
if (platform == .sdl3) {
|
||||||
|
if (b.lazyDependency("sdl3", .{ .optimize = optimize, .target = target })) |dep| {
|
||||||
|
raylib_artifact.root_module.linkLibrary(dep.artifact("SDL3"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var exe_mod: *std.Build.Module = undefined;
|
||||||
|
|
||||||
|
if (zig) {
|
||||||
|
exe_mod = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/core_basic_window.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
exe_mod.addImport("raylib", raylib_dep.module("raylib"));
|
||||||
|
} else {
|
||||||
|
exe_mod = b.createModule(.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.link_libc = true,
|
||||||
|
});
|
||||||
|
exe_mod.addCSourceFile(.{ .file = b.path("src/core_basic_window.c") });
|
||||||
|
exe_mod.linkLibrary(raylib_artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
|
||||||
|
// web exports are completely separate
|
||||||
|
if (target.query.os_tag == .emscripten) {
|
||||||
|
const emsdk = rl.emsdk;
|
||||||
|
const wasm = b.addLibrary(.{
|
||||||
|
.name = "core_basic_window_web",
|
||||||
|
.root_module = exe_mod,
|
||||||
|
});
|
||||||
|
|
||||||
|
const install_dir: std.Build.InstallDir = .{ .custom = "web" };
|
||||||
|
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
|
||||||
|
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
|
||||||
|
|
||||||
|
const emcc_step = emsdk.emccStep(b, raylib_artifact, wasm, .{
|
||||||
|
.optimize = optimize,
|
||||||
|
.flags = emcc_flags,
|
||||||
|
.settings = emcc_settings,
|
||||||
|
.shell_file_path = emsdk.shell(raylib_dep),
|
||||||
|
.install_dir = install_dir,
|
||||||
|
});
|
||||||
|
b.getInstallStep().dependOn(emcc_step);
|
||||||
|
|
||||||
|
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
|
||||||
|
const emrun_step = emsdk.emrunStep(
|
||||||
|
b,
|
||||||
|
b.getInstallPath(install_dir, html_filename),
|
||||||
|
&.{},
|
||||||
|
);
|
||||||
|
|
||||||
|
emrun_step.dependOn(emcc_step);
|
||||||
|
run_step.dependOn(emrun_step);
|
||||||
|
} else {
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "core_basic_window",
|
||||||
|
.root_module = exe_mod,
|
||||||
|
.use_lld = target.result.os.tag == .windows,
|
||||||
|
});
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
projects/Zig/build.zig.zon
Normal file
23
projects/Zig/build.zig.zon
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
.{
|
||||||
|
.name = .example,
|
||||||
|
.version = "0.0.1",
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.paths = .{""},
|
||||||
|
|
||||||
|
.dependencies = .{
|
||||||
|
.raylib = .{
|
||||||
|
.path = "../../",
|
||||||
|
},
|
||||||
|
.emsdk = .{
|
||||||
|
.url = "git+https://github.com/emscripten-core/emsdk?ref=4.0.9#3bcf1dcd01f040f370e10fe673a092d9ed79ebb5",
|
||||||
|
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
|
||||||
|
},
|
||||||
|
.sdl3 = .{
|
||||||
|
.url = "git+https://codeberg.org/7Games/zig-sdl3?ref=master#6d418ef3ddae99098414a96a88bf5e5fdb41785e",
|
||||||
|
.hash = "sdl3-0.1.9-NmT1QwiEJwByePqkmArtppCHQn8Y7kiSWcncT_Mop8ie",
|
||||||
|
.lazy = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
.fingerprint = 0x6eec9b9f1a9d7aca,
|
||||||
|
}
|
||||||
83
projects/Zig/src/core_basic_window.c
Normal file
83
projects/Zig/src/core_basic_window.c
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [core] example - Basic window (adapted for HTML5 platform)
|
||||||
|
*
|
||||||
|
* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
|
||||||
|
* As you will notice, code structure is slightly different to the other examples...
|
||||||
|
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
|
||||||
|
*
|
||||||
|
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||||
|
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
int screenWidth = 800;
|
||||||
|
int screenHeight = 450;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
void UpdateDrawFrame(void); // Update and Draw one frame
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
|
||||||
|
#else
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
UpdateDrawFrame();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
void UpdateDrawFrame(void)
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: Update your variables here
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
73
projects/Zig/src/core_basic_window.zig
Normal file
73
projects/Zig/src/core_basic_window.zig
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
//*******************************************************************************************
|
||||||
|
//*
|
||||||
|
//* raylib [core] example - Basic window (adapted for HTML5 platform)
|
||||||
|
//*
|
||||||
|
//* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
|
||||||
|
//* As you will notice, code structure is slightly different to the other examples...
|
||||||
|
//* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
|
||||||
|
//*
|
||||||
|
//* This example has been created using raylib 6.0 (www.raylib.com)
|
||||||
|
//* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||||
|
//*
|
||||||
|
//* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||||
|
//* Rewrite in Zig by HaxSam (@haxsam)
|
||||||
|
//*
|
||||||
|
//*******************************************************************************************
|
||||||
|
|
||||||
|
const rl = @import("raylib");
|
||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
const screenWidth: c_int = 800;
|
||||||
|
const screenHeight: c_int = 450;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
pub fn main() void {
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||||
|
|
||||||
|
if (builtin.os.tag == .emscripten) {
|
||||||
|
std.os.emscripten.emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
|
||||||
|
} else {
|
||||||
|
rl.SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!rl.WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
UpdateDrawFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
rl.CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
fn UpdateDrawFrame() callconv(.c) void {
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// TODO: Update your variables here
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
rl.BeginDrawing();
|
||||||
|
|
||||||
|
rl.ClearBackground(rl.RAYWHITE);
|
||||||
|
|
||||||
|
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LIGHTGRAY);
|
||||||
|
|
||||||
|
rl.EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
@ -26,13 +26,13 @@ REM Checks if cl is available and skips to the argument loop if it is
|
||||||
REM (Prevents calling vcvarsall every time you run this script)
|
REM (Prevents calling vcvarsall every time you run this script)
|
||||||
WHERE cl >nul 2>nul
|
WHERE cl >nul 2>nul
|
||||||
IF %ERRORLEVEL% == 0 goto READ_ARGS
|
IF %ERRORLEVEL% == 0 goto READ_ARGS
|
||||||
|
|
||||||
REM Activate the msvc build environment if cl isn't available yet
|
REM Activate the msvc build environment if cl isn't available yet
|
||||||
IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" (
|
for /f "tokens=*" %%i in (
|
||||||
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat"
|
'"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath 2^>nul'
|
||||||
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" (
|
) do set VS_PATH=%%i
|
||||||
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"
|
IF defined VS_PATH (
|
||||||
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" (
|
set VC_INIT="%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat"
|
||||||
set VC_INIT="C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
|
|
||||||
) ELSE (
|
) ELSE (
|
||||||
REM Initialize your vc environment here if the defaults don't work
|
REM Initialize your vc environment here if the defaults don't work
|
||||||
REM set VC_INIT="C:\your\path\here\vcvarsall.bat"
|
REM set VC_INIT="C:\your\path\here\vcvarsall.bat"
|
||||||
|
|
@ -167,7 +167,7 @@ IF NOT EXIST !TEMP_DIR!\ (
|
||||||
cd !TEMP_DIR!
|
cd !TEMP_DIR!
|
||||||
REM raylib source folder
|
REM raylib source folder
|
||||||
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
|
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
|
||||||
set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c"
|
set RAYLIB_C_FILES="!RAYLIB_SRC!\rcore.c" "!RAYLIB_SRC!\rshapes.c" "!RAYLIB_SRC!\rtextures.c" "!RAYLIB_SRC!\rtext.c" "!RAYLIB_SRC!\rmodels.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c"
|
||||||
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
|
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
|
||||||
|
|
||||||
IF DEFINED REALLY_QUIET (
|
IF DEFINED REALLY_QUIET (
|
||||||
|
|
|
||||||
56
src/Makefile
56
src/Makefile
|
|
@ -275,15 +275,28 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||||
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
||||||
#GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
|
#GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE # Uncomment to use software rendering
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
|
||||||
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
|
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
|
||||||
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
||||||
#GRAPHICS = GRAPHICS_API_OPENGL_ES3
|
#GRAPHICS = GRAPHICS_API_OPENGL_ES3
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW)
|
||||||
|
# On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0
|
||||||
|
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
||||||
|
#GRAPHICS = GRAPHICS_API_OPENGL_ES3
|
||||||
|
|
||||||
|
ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
$(error WEB_RGFW: Software rendering not supported!)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||||
# By default use OpenGL ES 2.0 on Android
|
# By default use OpenGL ES 2.0 on Android
|
||||||
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
GRAPHICS ?= GRAPHICS_API_OPENGL_ES2
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_MEMORY)
|
||||||
|
# By default use OpenGL Software
|
||||||
|
GRAPHICS = GRAPHICS_API_OPENGL_SOFTWARE
|
||||||
|
endif
|
||||||
|
|
||||||
# Define default C compiler and archiver to pack library: CC, AR
|
# Define default C compiler and archiver to pack library: CC, AR
|
||||||
#------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -320,7 +333,12 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||||
AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar
|
AR = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-ar
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
|
||||||
|
# HTML5 emscripten compiler
|
||||||
|
CC = emcc
|
||||||
|
AR = emar
|
||||||
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW)
|
||||||
# HTML5 emscripten compiler
|
# HTML5 emscripten compiler
|
||||||
CC = emcc
|
CC = emcc
|
||||||
AR = emar
|
AR = emar
|
||||||
|
|
@ -364,7 +382,6 @@ ifneq ($(RAYLIB_CONFIG_FLAGS), NONE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||||
# NOTE: When using multi-threading in the user code, it requires -pthread enabled
|
|
||||||
CFLAGS += -std=gnu99
|
CFLAGS += -std=gnu99
|
||||||
else
|
else
|
||||||
CFLAGS += -std=c99
|
CFLAGS += -std=c99
|
||||||
|
|
@ -383,12 +400,15 @@ ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
|
ifeq ($(RAYLIB_BUILD_MODE),RELEASE)
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
|
||||||
CFLAGS += -Os
|
|
||||||
endif
|
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||||
CFLAGS += -O1
|
CFLAGS += -O1
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
|
||||||
|
CFLAGS += -Os
|
||||||
|
endif
|
||||||
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW)
|
||||||
|
CFLAGS += -Os
|
||||||
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||||
CFLAGS += -O2
|
CFLAGS += -O2
|
||||||
endif
|
endif
|
||||||
|
|
@ -402,23 +422,12 @@ endif
|
||||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||||
CFLAGS += -Werror=implicit-function-declaration
|
CFLAGS += -Werror=implicit-function-declaration
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
|
||||||
# -Os # size optimization
|
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
||||||
# -O2 # optimization level 2, if used, also set --memory-init-file 0
|
CFLAGS += --profiling
|
||||||
# -sUSE_GLFW=3 # Use glfw3 library (context/input management)
|
endif
|
||||||
# -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
|
endif
|
||||||
# -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB)
|
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB_RGFW)
|
||||||
# -sUSE_PTHREADS=1 # multithreading support
|
|
||||||
# -sWASM=0 # disable Web Assembly, emitted by default
|
|
||||||
# -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
|
|
||||||
# -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data
|
|
||||||
# -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
|
|
||||||
# -sMINIFY_HTML=0 # minify generated html from shell.html
|
|
||||||
# --profiling # include information for code profiling
|
|
||||||
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
|
||||||
# --preload-file resources # specify a resources folder for data compilation
|
|
||||||
# --source-map-base # allow debugging in browser with source map
|
|
||||||
# --shell-file shell.html # define a custom shell .html and output extension
|
|
||||||
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
ifeq ($(RAYLIB_BUILD_MODE),DEBUG)
|
||||||
CFLAGS += --profiling
|
CFLAGS += --profiling
|
||||||
endif
|
endif
|
||||||
|
|
@ -768,7 +777,6 @@ all: raylib
|
||||||
raylib: $(OBJS)
|
raylib: $(OBJS)
|
||||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||||
# Compile raylib libray for web
|
# Compile raylib libray for web
|
||||||
#$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc
|
|
||||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||||
@echo "WARNING: $(TARGET_PLATFORM) does not support SHARED libraries. Generating STATIC library."
|
@echo "WARNING: $(TARGET_PLATFORM) does not support SHARED libraries. Generating STATIC library."
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
11
src/config.h
11
src/config.h
|
|
@ -73,7 +73,7 @@
|
||||||
#define SUPPORT_RPRAND_GENERATOR 1
|
#define SUPPORT_RPRAND_GENERATOR 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef SUPPORT_MOUSE_GESTURES
|
#ifndef SUPPORT_MOUSE_GESTURES
|
||||||
// Mouse gestures are directly mapped like touches and processed by gestures system
|
// Mouse gestures are directly mapped like touches and processed by the gestures system
|
||||||
#define SUPPORT_MOUSE_GESTURES 1
|
#define SUPPORT_MOUSE_GESTURES 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef SUPPORT_SSH_KEYBOARD_RPI
|
#ifndef SUPPORT_SSH_KEYBOARD_RPI
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// rcore: Configuration values
|
// rcore: Configuration values
|
||||||
// NOTE: Below values are alread defined inside [rcore.c] so there is no need to be
|
// NOTE: Below values are already defined inside [rcore.c] so there is no need to be
|
||||||
// redefined here, in case it must be done, uncomment the required line and update
|
// redefined here, in case it must be done, uncomment the required line and update
|
||||||
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -159,7 +159,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// rlgl: Configuration values
|
// rlgl: Configuration values
|
||||||
// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be
|
// NOTE: Below values are already defined inside [rlgl.h] so there is no need to be
|
||||||
// redefined here, in case it must be done, uncomment the required line and update
|
// redefined here, in case it must be done, uncomment the required line and update
|
||||||
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -252,6 +252,9 @@
|
||||||
#ifndef SUPPORT_FILEFORMAT_PIC
|
#ifndef SUPPORT_FILEFORMAT_PIC
|
||||||
#define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default
|
#define SUPPORT_FILEFORMAT_PIC 0 // Disabled by default
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SUPPORT_FILEFORMAT_PNM
|
||||||
|
#define SUPPORT_FILEFORMAT_PNM 0 // Disabled by default
|
||||||
|
#endif
|
||||||
#ifndef SUPPORT_FILEFORMAT_KTX
|
#ifndef SUPPORT_FILEFORMAT_KTX
|
||||||
#define SUPPORT_FILEFORMAT_KTX 0 // Disabled by default
|
#define SUPPORT_FILEFORMAT_KTX 0 // Disabled by default
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -349,7 +352,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// raudio: Configuration values
|
// raudio: Configuration values
|
||||||
// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be
|
// NOTE: Below values are already defined inside [rlgl.h] so there is no need to be
|
||||||
// redefined here, in case it must be done, uncomment the required line and update
|
// redefined here, in case it must be done, uncomment the required line and update
|
||||||
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
209
src/external/cgltf.h
vendored
209
src/external/cgltf.h
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* cgltf - a single-file glTF 2.0 parser written in C99.
|
* cgltf - a single-file glTF 2.0 parser written in C99.
|
||||||
*
|
*
|
||||||
* Version: 1.14
|
* Version: 1.15
|
||||||
*
|
*
|
||||||
* Website: https://github.com/jkuhlmann/cgltf
|
* Website: https://github.com/jkuhlmann/cgltf
|
||||||
*
|
*
|
||||||
|
|
@ -141,7 +141,7 @@ typedef struct cgltf_memory_options
|
||||||
typedef struct cgltf_file_options
|
typedef struct cgltf_file_options
|
||||||
{
|
{
|
||||||
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
||||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
|
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size);
|
||||||
void* user_data;
|
void* user_data;
|
||||||
} cgltf_file_options;
|
} cgltf_file_options;
|
||||||
|
|
||||||
|
|
@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter {
|
||||||
cgltf_meshopt_compression_filter_octahedral,
|
cgltf_meshopt_compression_filter_octahedral,
|
||||||
cgltf_meshopt_compression_filter_quaternion,
|
cgltf_meshopt_compression_filter_quaternion,
|
||||||
cgltf_meshopt_compression_filter_exponential,
|
cgltf_meshopt_compression_filter_exponential,
|
||||||
|
cgltf_meshopt_compression_filter_color,
|
||||||
cgltf_meshopt_compression_filter_max_enum
|
cgltf_meshopt_compression_filter_max_enum
|
||||||
} cgltf_meshopt_compression_filter;
|
} cgltf_meshopt_compression_filter;
|
||||||
|
|
||||||
|
|
@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression
|
||||||
cgltf_size count;
|
cgltf_size count;
|
||||||
cgltf_meshopt_compression_mode mode;
|
cgltf_meshopt_compression_mode mode;
|
||||||
cgltf_meshopt_compression_filter filter;
|
cgltf_meshopt_compression_filter filter;
|
||||||
|
cgltf_bool is_khr;
|
||||||
} cgltf_meshopt_compression;
|
} cgltf_meshopt_compression;
|
||||||
|
|
||||||
typedef struct cgltf_buffer_view
|
typedef struct cgltf_buffer_view
|
||||||
|
|
@ -376,13 +378,29 @@ typedef struct cgltf_image
|
||||||
cgltf_extension* extensions;
|
cgltf_extension* extensions;
|
||||||
} cgltf_image;
|
} cgltf_image;
|
||||||
|
|
||||||
|
typedef enum cgltf_filter_type {
|
||||||
|
cgltf_filter_type_undefined = 0,
|
||||||
|
cgltf_filter_type_nearest = 9728,
|
||||||
|
cgltf_filter_type_linear = 9729,
|
||||||
|
cgltf_filter_type_nearest_mipmap_nearest = 9984,
|
||||||
|
cgltf_filter_type_linear_mipmap_nearest = 9985,
|
||||||
|
cgltf_filter_type_nearest_mipmap_linear = 9986,
|
||||||
|
cgltf_filter_type_linear_mipmap_linear = 9987
|
||||||
|
} cgltf_filter_type;
|
||||||
|
|
||||||
|
typedef enum cgltf_wrap_mode {
|
||||||
|
cgltf_wrap_mode_clamp_to_edge = 33071,
|
||||||
|
cgltf_wrap_mode_mirrored_repeat = 33648,
|
||||||
|
cgltf_wrap_mode_repeat = 10497
|
||||||
|
} cgltf_wrap_mode;
|
||||||
|
|
||||||
typedef struct cgltf_sampler
|
typedef struct cgltf_sampler
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
cgltf_int mag_filter;
|
cgltf_filter_type mag_filter;
|
||||||
cgltf_int min_filter;
|
cgltf_filter_type min_filter;
|
||||||
cgltf_int wrap_s;
|
cgltf_wrap_mode wrap_s;
|
||||||
cgltf_int wrap_t;
|
cgltf_wrap_mode wrap_t;
|
||||||
cgltf_extras extras;
|
cgltf_extras extras;
|
||||||
cgltf_size extensions_count;
|
cgltf_size extensions_count;
|
||||||
cgltf_extension* extensions;
|
cgltf_extension* extensions;
|
||||||
|
|
@ -500,6 +518,14 @@ typedef struct cgltf_iridescence
|
||||||
cgltf_texture_view iridescence_thickness_texture;
|
cgltf_texture_view iridescence_thickness_texture;
|
||||||
} cgltf_iridescence;
|
} cgltf_iridescence;
|
||||||
|
|
||||||
|
typedef struct cgltf_diffuse_transmission
|
||||||
|
{
|
||||||
|
cgltf_texture_view diffuse_transmission_texture;
|
||||||
|
cgltf_float diffuse_transmission_factor;
|
||||||
|
cgltf_float diffuse_transmission_color_factor[3];
|
||||||
|
cgltf_texture_view diffuse_transmission_color_texture;
|
||||||
|
} cgltf_diffuse_transmission;
|
||||||
|
|
||||||
typedef struct cgltf_anisotropy
|
typedef struct cgltf_anisotropy
|
||||||
{
|
{
|
||||||
cgltf_float anisotropy_strength;
|
cgltf_float anisotropy_strength;
|
||||||
|
|
@ -525,6 +551,7 @@ typedef struct cgltf_material
|
||||||
cgltf_bool has_sheen;
|
cgltf_bool has_sheen;
|
||||||
cgltf_bool has_emissive_strength;
|
cgltf_bool has_emissive_strength;
|
||||||
cgltf_bool has_iridescence;
|
cgltf_bool has_iridescence;
|
||||||
|
cgltf_bool has_diffuse_transmission;
|
||||||
cgltf_bool has_anisotropy;
|
cgltf_bool has_anisotropy;
|
||||||
cgltf_bool has_dispersion;
|
cgltf_bool has_dispersion;
|
||||||
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
||||||
|
|
@ -537,6 +564,7 @@ typedef struct cgltf_material
|
||||||
cgltf_volume volume;
|
cgltf_volume volume;
|
||||||
cgltf_emissive_strength emissive_strength;
|
cgltf_emissive_strength emissive_strength;
|
||||||
cgltf_iridescence iridescence;
|
cgltf_iridescence iridescence;
|
||||||
|
cgltf_diffuse_transmission diffuse_transmission;
|
||||||
cgltf_anisotropy anisotropy;
|
cgltf_anisotropy anisotropy;
|
||||||
cgltf_dispersion dispersion;
|
cgltf_dispersion dispersion;
|
||||||
cgltf_texture_view normal_texture;
|
cgltf_texture_view normal_texture;
|
||||||
|
|
@ -743,6 +771,7 @@ typedef struct cgltf_data
|
||||||
{
|
{
|
||||||
cgltf_file_type file_type;
|
cgltf_file_type file_type;
|
||||||
void* file_data;
|
void* file_data;
|
||||||
|
cgltf_size file_size;
|
||||||
|
|
||||||
cgltf_asset asset;
|
cgltf_asset asset;
|
||||||
|
|
||||||
|
|
@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
|
||||||
|
|
||||||
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
||||||
|
|
||||||
|
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index);
|
||||||
|
|
||||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
||||||
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
||||||
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
||||||
|
|
@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
|
||||||
return cgltf_result_success;
|
return cgltf_result_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
|
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size)
|
||||||
{
|
{
|
||||||
(void)file_options;
|
(void)file_options;
|
||||||
|
(void)size;
|
||||||
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
||||||
memfree(memory_options->user_data, data);
|
memfree(memory_options->user_data, data);
|
||||||
}
|
}
|
||||||
|
|
@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||||
}
|
}
|
||||||
|
|
||||||
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
||||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
|
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||||
|
|
||||||
void* file_data = NULL;
|
void* file_data = NULL;
|
||||||
cgltf_size file_size = 0;
|
cgltf_size file_size = 0;
|
||||||
|
|
@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||||
|
|
||||||
if (result != cgltf_result_success)
|
if (result != cgltf_result_success)
|
||||||
{
|
{
|
||||||
file_release(&options->memory, &options->file, file_data);
|
file_release(&options->memory, &options->file, file_data, file_size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*out_data)->file_data = file_data;
|
(*out_data)->file_data = file_data;
|
||||||
|
(*out_data)->file_size = file_size;
|
||||||
|
|
||||||
return cgltf_result_success;
|
return cgltf_result_success;
|
||||||
}
|
}
|
||||||
|
|
@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data)
|
||||||
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
||||||
|
|
||||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
|
|
||||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
|
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
|
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
||||||
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
||||||
|
|
@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
|
|
||||||
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
||||||
{
|
{
|
||||||
file_release(&data->memory, &data->file, data->buffers[i].data);
|
file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size);
|
||||||
}
|
}
|
||||||
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
||||||
{
|
{
|
||||||
|
|
@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data)
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
||||||
|
|
||||||
file_release(&data->memory, &data->file, data->file_data);
|
file_release(&data->memory, &data->file, data->file_data, data->file_size);
|
||||||
|
|
||||||
data->memory.free_func(data->memory.user_data, data);
|
data->memory.free_func(data->memory.user_data, data);
|
||||||
}
|
}
|
||||||
|
|
@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index)
|
||||||
|
{
|
||||||
|
for (cgltf_size i = 0; i < prim->attributes_count; ++i)
|
||||||
|
{
|
||||||
|
const cgltf_attribute* attr = &prim->attributes[i];
|
||||||
|
if (attr->type == type && attr->index == index)
|
||||||
|
return attr->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle)
|
||||||
|
{
|
||||||
|
const cgltf_accessor_sparse* sparse = &accessor->sparse;
|
||||||
|
const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
|
||||||
|
const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view);
|
||||||
|
|
||||||
|
if (index_data == NULL || value_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
index_data += sparse->indices_byte_offset;
|
||||||
|
value_data += sparse->values_byte_offset;
|
||||||
|
|
||||||
|
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
|
||||||
|
|
||||||
|
cgltf_size offset = 0;
|
||||||
|
cgltf_size length = sparse->count;
|
||||||
|
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
cgltf_size rem = length % 2;
|
||||||
|
length /= 2;
|
||||||
|
|
||||||
|
cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type);
|
||||||
|
offset += index < needle ? length + rem : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == sparse->count)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type);
|
||||||
|
return index == needle ? value_data + offset * accessor->stride : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0;
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2460,7 +2540,9 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0;
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
|
||||||
{
|
{
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
{
|
{
|
||||||
return 0; // This is an error case, but we can't communicate the error with existing interface.
|
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||||
|
if (element)
|
||||||
|
return cgltf_component_read_index(element, accessor->component_type);
|
||||||
}
|
}
|
||||||
if (accessor->buffer_view == NULL)
|
if (accessor->buffer_view == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
return accessor->count;
|
return accessor->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
index_count = accessor->count < index_count ? accessor->count : index_count;
|
cgltf_size numbers_per_element = cgltf_num_components(accessor->type);
|
||||||
|
cgltf_size available_numbers = accessor->count * numbers_per_element;
|
||||||
|
|
||||||
|
index_count = available_numbers < index_count ? available_numbers : index_count;
|
||||||
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
||||||
|
|
||||||
if (accessor->is_sparse)
|
if (accessor->is_sparse)
|
||||||
|
|
@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
}
|
}
|
||||||
element += accessor->offset;
|
element += accessor->offset;
|
||||||
|
|
||||||
if (index_component_size == out_component_size && accessor->stride == out_component_size)
|
if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element)
|
||||||
{
|
{
|
||||||
memcpy(out, element, index_count * index_component_size);
|
memcpy(out, element, index_count * index_component_size);
|
||||||
return index_count;
|
return index_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data couldn't be copied with memcpy due to stride being larger than the component size.
|
||||||
|
// OR
|
||||||
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
||||||
switch (out_component_size)
|
switch (out_component_size)
|
||||||
{
|
{
|
||||||
|
case 1:
|
||||||
|
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||||
|
{
|
||||||
|
((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||||
{
|
{
|
||||||
|
|
@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return index_count;
|
return index_count;
|
||||||
|
|
@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const*
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission)
|
||||||
|
{
|
||||||
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
int size = tokens[i].size;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f);
|
||||||
|
out_diff_transmission->diffuse_transmission_factor = 0.f;
|
||||||
|
|
||||||
|
for (int j = 0; j < size; ++j)
|
||||||
|
{
|
||||||
|
CGLTF_CHECK_KEY(tokens[i]);
|
||||||
|
|
||||||
|
if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture);
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3);
|
||||||
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0)
|
||||||
|
{
|
||||||
|
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = cgltf_skip_json(tokens, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
||||||
{
|
{
|
||||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
|
@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||||
(void)options;
|
(void)options;
|
||||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||||
|
|
||||||
out_sampler->wrap_s = 10497;
|
out_sampler->wrap_s = cgltf_wrap_mode_repeat;
|
||||||
out_sampler->wrap_t = 10497;
|
out_sampler->wrap_t = cgltf_wrap_mode_repeat;
|
||||||
|
|
||||||
int size = tokens[i].size;
|
int size = tokens[i].size;
|
||||||
++i;
|
++i;
|
||||||
|
|
@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->mag_filter
|
out_sampler->mag_filter
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->min_filter
|
out_sampler->min_filter
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->wrap_s
|
out_sampler->wrap_s
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
out_sampler->wrap_t
|
out_sampler->wrap_t
|
||||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
||||||
|
|
@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
|
||||||
out_material->has_iridescence = 1;
|
out_material->has_iridescence = 1;
|
||||||
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0)
|
||||||
|
{
|
||||||
|
out_material->has_diffuse_transmission = 1;
|
||||||
|
i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission);
|
||||||
|
}
|
||||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
||||||
{
|
{
|
||||||
out_material->has_anisotropy = 1;
|
out_material->has_anisotropy = 1;
|
||||||
|
|
@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
|
||||||
{
|
{
|
||||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0)
|
||||||
|
{
|
||||||
|
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
|
||||||
out_buffer_view->has_meshopt_compression = 1;
|
out_buffer_view->has_meshopt_compression = 1;
|
||||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||||
}
|
}
|
||||||
|
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0)
|
||||||
|
{
|
||||||
|
out_buffer_view->has_meshopt_compression = 1;
|
||||||
|
out_buffer_view->meshopt_compression.is_khr = 1;
|
||||||
|
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
||||||
|
|
@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data)
|
||||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
||||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
||||||
|
|
||||||
|
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count);
|
||||||
|
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count);
|
||||||
|
|
||||||
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1565
src/external/cgltf_write.h
vendored
Normal file
1565
src/external/cgltf_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
308
src/external/dr_flac.h
vendored
308
src/external/dr_flac.h
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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.13.0 - TBD
|
dr_flac - v0.13.4 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRFLAC_VERSION_MAJOR 0
|
#define DRFLAC_VERSION_MAJOR 0
|
||||||
#define DRFLAC_VERSION_MINOR 13
|
#define DRFLAC_VERSION_MINOR 13
|
||||||
#define DRFLAC_VERSION_REVISION 0
|
#define DRFLAC_VERSION_REVISION 4
|
||||||
#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. */
|
||||||
|
|
@ -331,6 +331,12 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
drflac_uint32 type;
|
drflac_uint32 type;
|
||||||
|
|
||||||
|
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||||
|
drflac_uint32 rawDataSize;
|
||||||
|
|
||||||
|
/* The offset in the stream of the raw data. */
|
||||||
|
drflac_uint64 rawDataOffset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
||||||
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
||||||
|
|
@ -338,9 +344,6 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
const void* pRawData;
|
const void* pRawData;
|
||||||
|
|
||||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
|
||||||
drflac_uint32 rawDataSize;
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
drflac_streaminfo streaminfo;
|
drflac_streaminfo streaminfo;
|
||||||
|
|
@ -392,6 +395,7 @@ typedef struct
|
||||||
drflac_uint32 colorDepth;
|
drflac_uint32 colorDepth;
|
||||||
drflac_uint32 indexColorCount;
|
drflac_uint32 indexColorCount;
|
||||||
drflac_uint32 pictureDataSize;
|
drflac_uint32 pictureDataSize;
|
||||||
|
drflac_uint64 pictureDataOffset; /* Offset from the start of the stream. */
|
||||||
const drflac_uint8* pPictureData;
|
const drflac_uint8* pPictureData;
|
||||||
} picture;
|
} picture;
|
||||||
} data;
|
} data;
|
||||||
|
|
@ -1543,6 +1547,8 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
|
||||||
#define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
|
#define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DRFLAC_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
|
#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
|
||||||
|
|
||||||
/* Result Codes */
|
/* Result Codes */
|
||||||
|
|
@ -2712,9 +2718,17 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#if defined(DRFLAC_X64)
|
#if defined(DRFLAC_X64)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
A note on lzcnt.
|
||||||
|
|
||||||
|
We check for the presence of the lzcnt instruction at runtime before calling this function, but we still generate this code. I have had
|
||||||
|
a report where the assembler does not recognize the lzcnt instruction. To work around this we are going to use `rep; bsr` instead which
|
||||||
|
has an identical byte encoding as lzcnt, and should hopefully improve compatibility with older assemblers.
|
||||||
|
*/
|
||||||
drflac_uint64 r;
|
drflac_uint64 r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
"rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||||
|
/*"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||||
);
|
);
|
||||||
|
|
||||||
return (drflac_uint32)r;
|
return (drflac_uint32)r;
|
||||||
|
|
@ -2723,12 +2737,13 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||||
{
|
{
|
||||||
drflac_uint32 r;
|
drflac_uint32 r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
"rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||||
|
/*"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||||
);
|
);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||||
{
|
{
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
|
|
@ -5967,8 +5982,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
|
||||||
break; /* Failed to seek to FLAC frame. */
|
break; /* Failed to seek to FLAC frame. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
|
|
||||||
|
|
||||||
if (pcmRangeLo > pcmFrameIndex) {
|
if (pcmRangeLo > pcmFrameIndex) {
|
||||||
/* We seeked too far forward. We need to move our target byte backward and try again. */
|
/* We seeked too far forward. We need to move our target byte backward and try again. */
|
||||||
byteRangeHi = lastSuccessfulSeekOffset;
|
byteRangeHi = lastSuccessfulSeekOffset;
|
||||||
|
|
@ -5991,12 +6004,14 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
|
||||||
break; /* Failed to seek to FLAC frame. */
|
break; /* Failed to seek to FLAC frame. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const double approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0);
|
||||||
|
|
||||||
byteRangeLo = lastSuccessfulSeekOffset;
|
byteRangeLo = lastSuccessfulSeekOffset;
|
||||||
if (byteRangeHi < byteRangeLo) {
|
if (byteRangeHi < byteRangeLo) {
|
||||||
byteRangeHi = byteRangeLo;
|
byteRangeHi = byteRangeLo;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio);
|
targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0) * approxCompressionRatio);
|
||||||
if (targetByte > byteRangeHi) {
|
if (targetByte > byteRangeHi) {
|
||||||
targetByte = byteRangeHi;
|
targetByte = byteRangeHi;
|
||||||
}
|
}
|
||||||
|
|
@ -6389,7 +6404,7 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
DRFLAC_COPY_MEMORY(p2, p, szOld);
|
DRFLAC_COPY_MEMORY(p2, p, DRFLAC_MIN(szNew, szOld));
|
||||||
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
|
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6420,8 +6435,19 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
drflac_uint64 runningFilePos = 42;
|
drflac_uint64 runningFilePos = 42;
|
||||||
drflac_uint64 seektablePos = 0;
|
drflac_uint64 seektablePos = 0;
|
||||||
drflac_uint32 seektableSize = 0;
|
drflac_uint32 seektableSize = 0;
|
||||||
|
drflac_int64 fileSize = 0;
|
||||||
|
drflac_bool32 hasKnownFileSize = DRFLAC_FALSE;
|
||||||
|
|
||||||
(void)onTell;
|
/* We'll be doing some memory allocations here against untrusted data. We'll do a basic validation check that they don't exceed the size of the file. */
|
||||||
|
if (onTell != NULL && onSeek != NULL) {
|
||||||
|
if (onSeek(pUserData, 0, DRFLAC_SEEK_END)) {
|
||||||
|
if (onTell(pUserData, &fileSize)) {
|
||||||
|
hasKnownFileSize = DRFLAC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSeek(pUserData, runningFilePos, DRFLAC_SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
drflac_metadata metadata;
|
drflac_metadata metadata;
|
||||||
|
|
@ -6431,11 +6457,17 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
|
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasKnownFileSize && (blockSize > ((drflac_uint64)fileSize - runningFilePos))) {
|
||||||
|
return DRFLAC_FALSE; /* Block size exceeds the size of the file. */
|
||||||
|
}
|
||||||
|
|
||||||
runningFilePos += 4;
|
runningFilePos += 4;
|
||||||
|
|
||||||
metadata.type = blockType;
|
metadata.type = blockType;
|
||||||
metadata.pRawData = NULL;
|
|
||||||
metadata.rawDataSize = 0;
|
metadata.rawDataSize = 0;
|
||||||
|
metadata.rawDataOffset = runningFilePos;
|
||||||
|
metadata.pRawData = NULL;
|
||||||
|
|
||||||
switch (blockType)
|
switch (blockType)
|
||||||
{
|
{
|
||||||
|
|
@ -6712,59 +6744,161 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData;
|
drflac_bool32 result = DRFLAC_TRUE;
|
||||||
const char* pRunningData;
|
drflac_uint32 blockSizeRemaining = blockSize;
|
||||||
const char* pRunningDataEnd;
|
char* pMime = NULL;
|
||||||
|
char* pDescription = NULL;
|
||||||
|
void* pPictureData = NULL;
|
||||||
|
|
||||||
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) {
|
||||||
if (pRawData == NULL) {
|
result = DRFLAC_FALSE;
|
||||||
return DRFLAC_FALSE;
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.type = drflac__be2host_32(metadata.data.picture.type);
|
||||||
|
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < metadata.data.picture.mimeLength) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
if (pMime == NULL) {
|
||||||
return DRFLAC_FALSE;
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.pRawData = pRawData;
|
if (onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
|
||||||
metadata.rawDataSize = blockSize;
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
pRunningData = (const char*)pRawData;
|
|
||||||
pRunningDataEnd = (const char*)pRawData + blockSize;
|
|
||||||
|
|
||||||
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
|
|
||||||
/* Need space for the rest of the block */
|
|
||||||
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
|
||||||
return DRFLAC_FALSE;
|
|
||||||
}
|
}
|
||||||
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
blockSizeRemaining -= metadata.data.picture.mimeLength;
|
||||||
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
pMime[metadata.data.picture.mimeLength] = '\0'; /* Null terminate for safety. */
|
||||||
|
metadata.data.picture.mime = (const char*)pMime;
|
||||||
|
|
||||||
/* Need space for the rest of the block */
|
|
||||||
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) {
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
result = DRFLAC_FALSE;
|
||||||
return DRFLAC_FALSE;
|
goto done_flac;
|
||||||
}
|
}
|
||||||
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
|
blockSizeRemaining -= 4;
|
||||||
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
|
||||||
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
|
||||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
|
||||||
|
|
||||||
/* Need space for the picture after the block */
|
if (blockSizeRemaining < metadata.data.picture.descriptionLength) {
|
||||||
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
result = DRFLAC_FALSE;
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
goto done_flac;
|
||||||
return DRFLAC_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||||
|
if (pDescription == NULL) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= metadata.data.picture.descriptionLength;
|
||||||
|
pDescription[metadata.data.picture.descriptionLength] = '\0'; /* Null terminate for safety. */
|
||||||
|
metadata.data.picture.description = (const char*)pDescription;
|
||||||
|
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.width = drflac__be2host_32(metadata.data.picture.width);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.height = drflac__be2host_32(metadata.data.picture.height);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.colorDepth = drflac__be2host_32(metadata.data.picture.colorDepth);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.indexColorCount = drflac__be2host_32(metadata.data.picture.indexColorCount);
|
||||||
|
|
||||||
|
|
||||||
|
/* Picture data. */
|
||||||
|
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
blockSizeRemaining -= 4;
|
||||||
|
metadata.data.picture.pictureDataSize = drflac__be2host_32(metadata.data.picture.pictureDataSize);
|
||||||
|
|
||||||
|
if (blockSizeRemaining < metadata.data.picture.pictureDataSize) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the actual image data we want to store the offset to the start of the stream. */
|
||||||
|
metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining);
|
||||||
|
|
||||||
|
/*
|
||||||
|
For the allocation of image data, we can allow memory allocation to fail, in which case we just leave
|
||||||
|
the pointer as null. If it fails, we need to fall back to seeking past the image data.
|
||||||
|
*/
|
||||||
|
#ifndef DR_FLAC_NO_PICTURE_METADATA_MALLOC
|
||||||
|
pPictureData = drflac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks);
|
||||||
|
if (pPictureData != NULL) {
|
||||||
|
if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Allocation failed. We need to seek past the picture data. */
|
||||||
|
if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, DRFLAC_SEEK_CUR)) {
|
||||||
|
result = DRFLAC_FALSE;
|
||||||
|
goto done_flac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockSizeRemaining -= metadata.data.picture.pictureDataSize;
|
||||||
|
(void)blockSizeRemaining;
|
||||||
|
|
||||||
|
metadata.data.picture.pPictureData = (const drflac_uint8*)pPictureData;
|
||||||
|
|
||||||
|
|
||||||
|
/* Only fire the callback if we actually have a way to read the image data. We must have either a valid offset, or a valid data pointer. */
|
||||||
|
if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) {
|
||||||
onMeta(pUserDataMD, &metadata);
|
onMeta(pUserDataMD, &metadata);
|
||||||
|
} else {
|
||||||
|
/* Don't have a valid offset or data pointer, so just pretend we don't have a picture metadata. */
|
||||||
|
}
|
||||||
|
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
done_flac:
|
||||||
|
drflac__free_from_callbacks(pMime, pAllocationCallbacks);
|
||||||
|
drflac__free_from_callbacks(pDescription, pAllocationCallbacks);
|
||||||
|
drflac__free_from_callbacks(pPictureData, pAllocationCallbacks);
|
||||||
|
|
||||||
|
if (result != DRFLAC_TRUE) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
@ -6800,14 +6934,17 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||||
*/
|
*/
|
||||||
if (onMeta) {
|
if (onMeta) {
|
||||||
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||||
if (pRawData == NULL) {
|
if (pRawData != NULL) {
|
||||||
return DRFLAC_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||||
return DRFLAC_FALSE;
|
return DRFLAC_FALSE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Allocation failed. We need to seek past the block. */
|
||||||
|
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||||
|
return DRFLAC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
metadata.pRawData = pRawData;
|
metadata.pRawData = pRawData;
|
||||||
metadata.rawDataSize = blockSize;
|
metadata.rawDataSize = blockSize;
|
||||||
|
|
@ -7985,11 +8122,17 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((0xFFFFFFFF - (seekpointCount * sizeof(drflac_seekpoint))) < allocationSize) {
|
||||||
|
#ifndef DR_FLAC_NO_OGG
|
||||||
|
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
allocationSize += seekpointCount * sizeof(drflac_seekpoint);
|
allocationSize += seekpointCount * sizeof(drflac_seekpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pFlac = (drflac*)drflac__malloc_from_callbacks((size_t)allocationSize, &allocationCallbacks);
|
||||||
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
|
|
||||||
if (pFlac == NULL) {
|
if (pFlac == NULL) {
|
||||||
#ifndef DR_FLAC_NO_OGG
|
#ifndef DR_FLAC_NO_OGG
|
||||||
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
||||||
|
|
@ -8699,7 +8842,7 @@ static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCurso
|
||||||
DRFLAC_ASSERT(pFileStdio != NULL);
|
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||||
DRFLAC_ASSERT(pCursor != NULL);
|
DRFLAC_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -8821,8 +8964,6 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_
|
||||||
|
|
||||||
DRFLAC_ASSERT(memoryStream != NULL);
|
DRFLAC_ASSERT(memoryStream != NULL);
|
||||||
|
|
||||||
newCursor = memoryStream->currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRFLAC_SEEK_SET) {
|
if (origin == DRFLAC_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||||
|
|
@ -11702,16 +11843,14 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
||||||
{ \
|
{ \
|
||||||
type* pSampleData = NULL; \
|
type* pSampleData = NULL; \
|
||||||
drflac_uint64 totalPCMFrameCount; \
|
drflac_uint64 totalPCMFrameCount; \
|
||||||
\
|
|
||||||
DRFLAC_ASSERT(pFlac != NULL); \
|
|
||||||
\
|
|
||||||
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
|
|
||||||
\
|
|
||||||
if (totalPCMFrameCount == 0) { \
|
|
||||||
type buffer[4096]; \
|
type buffer[4096]; \
|
||||||
drflac_uint64 pcmFramesRead; \
|
drflac_uint64 pcmFramesRead; \
|
||||||
size_t sampleDataBufferSize = sizeof(buffer); \
|
size_t sampleDataBufferSize = sizeof(buffer); \
|
||||||
\
|
\
|
||||||
|
DRFLAC_ASSERT(pFlac != NULL); \
|
||||||
|
\
|
||||||
|
totalPCMFrameCount = 0; \
|
||||||
|
\
|
||||||
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||||
if (pSampleData == NULL) { \
|
if (pSampleData == NULL) { \
|
||||||
goto on_error; \
|
goto on_error; \
|
||||||
|
|
@ -11740,19 +11879,6 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
||||||
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
||||||
protect those ears from random noise! */ \
|
protect those ears from random noise! */ \
|
||||||
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
||||||
} else { \
|
|
||||||
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
|
|
||||||
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
|
|
||||||
goto on_error; /* The decoded data is too big. */ \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \
|
|
||||||
if (pSampleData == NULL) { \
|
|
||||||
goto on_error; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
|
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
||||||
if (channelsOut) *channelsOut = pFlac->channels; \
|
if (channelsOut) *channelsOut = pFlac->channels; \
|
||||||
|
|
@ -12077,7 +12203,23 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.13.0 - TBD
|
v0.13.4 - TBD
|
||||||
|
- Add a bounds check when allocating memory during metadata processing.
|
||||||
|
- Fix a possible overflow error when parsing picture metadata.
|
||||||
|
|
||||||
|
v0.13.3 - 2026-01-17
|
||||||
|
- Fix a compiler compatibility issue with some inlined assembly.
|
||||||
|
- Fix a compilation warning.
|
||||||
|
|
||||||
|
v0.13.2 - 2025-12-02
|
||||||
|
- Improve robustness of the parsing of picture metadata to improve support for memory constrained embedded devices.
|
||||||
|
- Fix a warning about an assigned by unused variable.
|
||||||
|
- Improvements to drflac_open_and_read_pcm_frames_*() and family to avoid excessively large memory allocations from malformed files.
|
||||||
|
|
||||||
|
v0.13.1 - 2025-09-10
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
|
||||||
|
v0.13.0 - 2025-07-23
|
||||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
- 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_start -> DRFLAC_SEEK_SET
|
||||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||||
|
|
|
||||||
188
src/external/dr_mp3.h
vendored
188
src/external/dr_mp3.h
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||||
dr_mp3 - v0.7.0 - TBD
|
dr_mp3 - v0.7.4 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRMP3_VERSION_MAJOR 0
|
#define DRMP3_VERSION_MAJOR 0
|
||||||
#define DRMP3_VERSION_MINOR 7
|
#define DRMP3_VERSION_MINOR 7
|
||||||
#define DRMP3_VERSION_REVISION 0
|
#define DRMP3_VERSION_REVISION 4
|
||||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
|
|
@ -257,16 +257,45 @@ typedef struct
|
||||||
Low Level Push API
|
Low Level Push API
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
|
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||||
|
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||||
|
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
||||||
} drmp3dec_frame_info;
|
} drmp3dec_frame_info;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const drmp3_uint8 *buf;
|
||||||
|
int pos, limit;
|
||||||
|
} drmp3_bs;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const drmp3_uint8 *sfbtab;
|
||||||
|
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||||
|
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||||
|
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||||
|
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||||
|
} drmp3_L3_gr_info;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
drmp3_bs bs;
|
||||||
|
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||||
|
drmp3_L3_gr_info gr_info[4];
|
||||||
|
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||||
|
drmp3_uint8 ist_pos[2][39];
|
||||||
|
} drmp3dec_scratch;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
||||||
int reserv, free_format_bytes;
|
int reserv, free_format_bytes;
|
||||||
drmp3_uint8 header[4], reserv_buf[511];
|
drmp3_uint8 header[4], reserv_buf[511];
|
||||||
|
drmp3dec_scratch scratch;
|
||||||
} drmp3dec;
|
} drmp3dec;
|
||||||
|
|
||||||
/* Initializes a low level decoder. */
|
/* Initializes a low level decoder. */
|
||||||
|
|
@ -592,14 +621,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
|
|
||||||
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
||||||
|
|
||||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
|
||||||
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
||||||
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
|
||||||
|
|
||||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
|
||||||
#define DRMP3_SHORT_BLOCK_TYPE 2
|
#define DRMP3_SHORT_BLOCK_TYPE 2
|
||||||
#define DRMP3_STOP_BLOCK_TYPE 3
|
#define DRMP3_STOP_BLOCK_TYPE 3
|
||||||
#define DRMP3_MODE_MONO 3
|
#define DRMP3_MODE_MONO 3
|
||||||
|
|
@ -632,8 +657,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
|
|
||||||
#if !defined(DR_MP3_NO_SIMD)
|
#if !defined(DR_MP3_NO_SIMD)
|
||||||
|
|
||||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
#if !defined(DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
|
||||||
/* x64 always have SSE2, arm64 always have neon, no need for generic code */
|
#define DR_MP3_ONLY_SIMD
|
||||||
|
#endif
|
||||||
|
#if !defined(DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||||
#define DR_MP3_ONLY_SIMD
|
#define DR_MP3_ONLY_SIMD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -655,7 +682,7 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||||
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
||||||
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
||||||
typedef __m128 drmp3_f4;
|
typedef __m128 drmp3_f4;
|
||||||
#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
|
#if (defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)) && !defined(__clang__)
|
||||||
#define drmp3_cpuid __cpuid
|
#define drmp3_cpuid __cpuid
|
||||||
#else
|
#else
|
||||||
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
||||||
|
|
@ -779,11 +806,7 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
||||||
#define DRMP3_FREE(p) free((p))
|
#define DRMP3_FREE(p) free((p))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const drmp3_uint8 *buf;
|
|
||||||
int pos, limit;
|
|
||||||
} drmp3_bs;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
@ -796,24 +819,6 @@ typedef struct
|
||||||
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
||||||
} drmp3_L12_subband_alloc;
|
} drmp3_L12_subband_alloc;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const drmp3_uint8 *sfbtab;
|
|
||||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
|
||||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
|
||||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
|
||||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
|
||||||
} drmp3_L3_gr_info;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
drmp3_bs bs;
|
|
||||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
|
||||||
drmp3_L3_gr_info gr_info[4];
|
|
||||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
|
||||||
drmp3_uint8 ist_pos[2][39];
|
|
||||||
} drmp3dec_scratch;
|
|
||||||
|
|
||||||
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
||||||
{
|
{
|
||||||
bs->buf = data;
|
bs->buf = data;
|
||||||
|
|
@ -1227,6 +1232,14 @@ static float drmp3_L3_ldexp_q2(float y, int exp_q2)
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
I've had reports of GCC 14 throwing an incorrect -Wstringop-overflow warning here. This is an attempt
|
||||||
|
to silence this warning.
|
||||||
|
*/
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||||
|
#endif
|
||||||
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
||||||
{
|
{
|
||||||
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
||||||
|
|
@ -1288,6 +1301,9 @@ static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *is
|
||||||
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
static const float g_drmp3_pow43[129 + 16] = {
|
static const float g_drmp3_pow43[129 + 16] = {
|
||||||
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
|
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
|
||||||
|
|
@ -2299,7 +2315,6 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
int i = 0, igr, frame_size = 0, success = 1;
|
int i = 0, igr, frame_size = 0, success = 1;
|
||||||
const drmp3_uint8 *hdr;
|
const drmp3_uint8 *hdr;
|
||||||
drmp3_bs bs_frame[1];
|
drmp3_bs bs_frame[1];
|
||||||
drmp3dec_scratch scratch;
|
|
||||||
|
|
||||||
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
||||||
{
|
{
|
||||||
|
|
@ -2336,23 +2351,23 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
|
|
||||||
if (info->layer == 3)
|
if (info->layer == 3)
|
||||||
{
|
{
|
||||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
|
int main_data_begin = drmp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr);
|
||||||
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
||||||
{
|
{
|
||||||
drmp3dec_init(dec);
|
drmp3dec_init(dec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
|
success = drmp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin);
|
||||||
if (success && pcm != NULL)
|
if (success && pcm != NULL)
|
||||||
{
|
{
|
||||||
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
||||||
{
|
{
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
|
drmp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels);
|
||||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drmp3_L3_save_reservoir(dec, &scratch);
|
drmp3_L3_save_reservoir(dec, &dec->scratch);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
#ifdef DR_MP3_ONLY_MP3
|
#ifdef DR_MP3_ONLY_MP3
|
||||||
|
|
@ -2366,15 +2381,15 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||||
|
|
||||||
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
||||||
|
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
for (i = 0, igr = 0; igr < 3; igr++)
|
for (i = 0, igr = 0; igr < 3; igr++)
|
||||||
{
|
{
|
||||||
if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
if (12 == (i += drmp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
|
drmp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]);
|
||||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||||
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
||||||
}
|
}
|
||||||
if (bs_frame->pos > bs_frame->limit)
|
if (bs_frame->pos > bs_frame->limit)
|
||||||
|
|
@ -3005,6 +3020,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
((drmp3_uint32)ape[26] << 16) |
|
((drmp3_uint32)ape[26] << 16) |
|
||||||
((drmp3_uint32)ape[27] << 24);
|
((drmp3_uint32)ape[27] << 24);
|
||||||
|
|
||||||
|
if (32 + tagSize < streamLen) {
|
||||||
streamEndOffset -= 32 + tagSize;
|
streamEndOffset -= 32 + tagSize;
|
||||||
streamLen -= 32 + tagSize;
|
streamLen -= 32 + tagSize;
|
||||||
|
|
||||||
|
|
@ -3023,6 +3039,9 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* The tag size is larger than the stream. Invalid APE tag. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3153,7 +3172,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
{
|
{
|
||||||
drmp3_bs bs;
|
drmp3_bs bs;
|
||||||
drmp3_L3_gr_info grInfo[4];
|
drmp3_L3_gr_info grInfo[4];
|
||||||
const drmp3_uint8* pTagData = pFirstFrameData;
|
|
||||||
|
|
||||||
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
||||||
|
|
||||||
|
|
@ -3164,11 +3182,16 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
||||||
drmp3_bool32 isXing = DRMP3_FALSE;
|
drmp3_bool32 isXing = DRMP3_FALSE;
|
||||||
drmp3_bool32 isInfo = DRMP3_FALSE;
|
drmp3_bool32 isInfo = DRMP3_FALSE;
|
||||||
|
const drmp3_uint8* pTagData;
|
||||||
const drmp3_uint8* pTagDataBeg;
|
const drmp3_uint8* pTagDataBeg;
|
||||||
|
|
||||||
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
||||||
pTagData = pTagDataBeg;
|
pTagData = pTagDataBeg;
|
||||||
|
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) {
|
||||||
|
goto done_xing_info; /* Frame too small for a Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for both "Xing" and "Info" identifiers. */
|
/* Check for both "Xing" and "Info" identifiers. */
|
||||||
isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
|
isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
|
||||||
isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
|
isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
|
||||||
|
|
@ -3180,33 +3203,52 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
pTagData += 8; /* Skip past the ID and flags. */
|
pTagData += 8; /* Skip past the ID and flags. */
|
||||||
|
|
||||||
if (flags & 0x01) { /* FRAMES flag. */
|
if (flags & 0x01) { /* FRAMES flag. */
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
|
||||||
|
goto done_xing_info; /* Invalid Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
|
detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
|
||||||
pTagData += 4;
|
pTagData += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x02) { /* BYTES flag. */
|
if (flags & 0x02) { /* BYTES flag. */
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
|
||||||
|
goto done_xing_info; /* Invalid Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
|
bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
|
||||||
(void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */
|
(void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */
|
||||||
pTagData += 4;
|
pTagData += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x04) { /* TOC flag. */
|
if (flags & 0x04) { /* TOC flag. */
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) {
|
||||||
|
goto done_xing_info; /* Invalid Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Extract and bind seek points. */
|
/* TODO: Extract and bind seek points. */
|
||||||
pTagData += 100;
|
pTagData += 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x08) { /* SCALE flag. */
|
if (flags & 0x08) { /* SCALE flag. */
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
|
||||||
|
goto done_xing_info; /* Invalid Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
pTagData += 4;
|
pTagData += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */
|
/* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */
|
||||||
if (pTagData[0]) {
|
if (pTagData[0]) {
|
||||||
pTagData += 21;
|
|
||||||
|
|
||||||
if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) {
|
|
||||||
int delayInPCMFrames;
|
int delayInPCMFrames;
|
||||||
int paddingInPCMFrames;
|
int paddingInPCMFrames;
|
||||||
|
|
||||||
|
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) {
|
||||||
|
goto done_xing_info; /* Invalid Xing/Info tag. */
|
||||||
|
}
|
||||||
|
|
||||||
|
pTagData += 21;
|
||||||
|
|
||||||
delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
|
delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
|
||||||
paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
|
paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
|
||||||
if (paddingInPCMFrames < 0) {
|
if (paddingInPCMFrames < 0) {
|
||||||
|
|
@ -3216,7 +3258,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
|
pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
|
||||||
pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
|
pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
My understanding is that if the "Xing" header is present we can consider this to be a VBR stream and if the "Info" header is
|
My understanding is that if the "Xing" header is present we can consider this to be a VBR stream and if the "Info" header is
|
||||||
|
|
@ -3246,7 +3287,16 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
||||||
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
||||||
pMP3->streamCursor = pMP3->streamStartOffset;
|
pMP3->streamCursor = pMP3->streamStartOffset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The internal decoder needs to be reset to clear out any state. If we don't reset this state, it's possible for
|
||||||
|
there to be inconsistencies in the number of samples read when reading to the end of the stream depending on
|
||||||
|
whether or not the caller seeks to the start of the stream.
|
||||||
|
*/
|
||||||
|
drmp3dec_init(&pMP3->decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done_xing_info:;
|
||||||
} else {
|
} else {
|
||||||
/* Failed to read the side info. */
|
/* Failed to read the side info. */
|
||||||
}
|
}
|
||||||
|
|
@ -3259,7 +3309,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detectedMP3FrameCount != 0xFFFFFFFF) {
|
if (detectedMP3FrameCount != 0xFFFFFFFF) {
|
||||||
pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount;
|
pMP3->totalPCMFrameCount = (drmp3_uint64)detectedMP3FrameCount * firstFramePCMFrameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
pMP3->channels = pMP3->mp3FrameChannels;
|
pMP3->channels = pMP3->mp3FrameChannels;
|
||||||
|
|
@ -3307,8 +3357,6 @@ static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3
|
||||||
|
|
||||||
DRMP3_ASSERT(pMP3 != NULL);
|
DRMP3_ASSERT(pMP3 != NULL);
|
||||||
|
|
||||||
newCursor = pMP3->memory.currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRMP3_SEEK_SET) {
|
if (origin == DRMP3_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRMP3_SEEK_CUR) {
|
} else if (origin == DRMP3_SEEK_CUR) {
|
||||||
|
|
@ -3981,7 +4029,7 @@ static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor)
|
||||||
DRMP3_ASSERT(pFileStdio != NULL);
|
DRMP3_ASSERT(pFileStdio != NULL);
|
||||||
DRMP3_ASSERT(pCursor != NULL);
|
DRMP3_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -4223,7 +4271,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 frame
|
||||||
#else
|
#else
|
||||||
/* Slow path. Convert from s16 to f32. */
|
/* Slow path. Convert from s16 to f32. */
|
||||||
{
|
{
|
||||||
drmp3_int16 pTempS16[8192];
|
drmp3_int16 pTempS16[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
|
||||||
drmp3_uint64 totalPCMFramesRead = 0;
|
drmp3_uint64 totalPCMFramesRead = 0;
|
||||||
|
|
||||||
while (totalPCMFramesRead < framesToRead) {
|
while (totalPCMFramesRead < framesToRead) {
|
||||||
|
|
@ -4260,7 +4308,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 frame
|
||||||
#else
|
#else
|
||||||
/* Slow path. Convert from f32 to s16. */
|
/* Slow path. Convert from f32 to s16. */
|
||||||
{
|
{
|
||||||
float pTempF32[4096];
|
float pTempF32[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
|
||||||
drmp3_uint64 totalPCMFramesRead = 0;
|
drmp3_uint64 totalPCMFramesRead = 0;
|
||||||
|
|
||||||
while (totalPCMFramesRead < framesToRead) {
|
while (totalPCMFramesRead < framesToRead) {
|
||||||
|
|
@ -4748,7 +4796,7 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
|
||||||
drmp3_uint64 totalFramesRead = 0;
|
drmp3_uint64 totalFramesRead = 0;
|
||||||
drmp3_uint64 framesCapacity = 0;
|
drmp3_uint64 framesCapacity = 0;
|
||||||
float* pFrames = NULL;
|
float* pFrames = NULL;
|
||||||
float temp[4096];
|
float temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
|
||||||
|
|
||||||
DRMP3_ASSERT(pMP3 != NULL);
|
DRMP3_ASSERT(pMP3 != NULL);
|
||||||
|
|
||||||
|
|
@ -4780,6 +4828,8 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
|
||||||
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||||
if (pNewFrames == NULL) {
|
if (pNewFrames == NULL) {
|
||||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||||
|
pFrames = NULL;
|
||||||
|
totalFramesRead = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4815,7 +4865,7 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
|
||||||
drmp3_uint64 totalFramesRead = 0;
|
drmp3_uint64 totalFramesRead = 0;
|
||||||
drmp3_uint64 framesCapacity = 0;
|
drmp3_uint64 framesCapacity = 0;
|
||||||
drmp3_int16* pFrames = NULL;
|
drmp3_int16* pFrames = NULL;
|
||||||
drmp3_int16 temp[4096];
|
drmp3_int16 temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
|
||||||
|
|
||||||
DRMP3_ASSERT(pMP3 != NULL);
|
DRMP3_ASSERT(pMP3 != NULL);
|
||||||
|
|
||||||
|
|
@ -4847,6 +4897,8 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
|
||||||
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||||
if (pNewFrames == NULL) {
|
if (pNewFrames == NULL) {
|
||||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||||
|
pFrames = NULL;
|
||||||
|
totalFramesRead = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4981,7 +5033,27 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.7.0 - TBD
|
v0.7.4 - TBD
|
||||||
|
- Fix an overflow error with "Xing" and "Info" tag parsing.
|
||||||
|
- Add some validation checks for "Xing" and "Info" tag parsing.
|
||||||
|
- Reduce size of some stack allocations.
|
||||||
|
- Improvements to SIMD detection.
|
||||||
|
|
||||||
|
v0.7.3 - 2026-01-17
|
||||||
|
- Fix an error in drmp3_open_and_read_pcm_frames_s16() and family when memory allocation fails.
|
||||||
|
- Fix some compilation warnings.
|
||||||
|
|
||||||
|
v0.7.2 - 2025-12-02
|
||||||
|
- Reduce stack space to improve robustness on embedded systems.
|
||||||
|
- Fix a compilation error with MSVC Clang toolset relating to cpuid.
|
||||||
|
- Fix an error with APE tag parsing.
|
||||||
|
|
||||||
|
v0.7.1 - 2025-09-10
|
||||||
|
- Silence a warning with GCC.
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
- Fix a decoding inconsistency when seeking. Prior to this change, reading to the end of the stream immediately after initializing will result in a different number of samples read than if the stream is seeked to the start and read to the end.
|
||||||
|
|
||||||
|
v0.7.0 - 2025-07-23
|
||||||
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
||||||
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
||||||
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
||||||
|
|
|
||||||
186
src/external/dr_wav.h
vendored
186
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.14.0 - TBD
|
dr_wav - v0.14.6 - TBD
|
||||||
|
|
||||||
David Reid - mackron@gmail.com
|
David Reid - mackron@gmail.com
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ extern "C" {
|
||||||
|
|
||||||
#define DRWAV_VERSION_MAJOR 0
|
#define DRWAV_VERSION_MAJOR 0
|
||||||
#define DRWAV_VERSION_MINOR 14
|
#define DRWAV_VERSION_MINOR 14
|
||||||
#define DRWAV_VERSION_REVISION 0
|
#define DRWAV_VERSION_REVISION 6
|
||||||
#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. */
|
||||||
|
|
@ -1971,7 +1971,15 @@ DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void
|
||||||
return DRWAV_INVALID_FILE;
|
return DRWAV_INVALID_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24; /* <-- Subtract 24 because w64 includes the size of the header. */
|
pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes);
|
||||||
|
|
||||||
|
/* Subtract 24 from the size because with w64 the reported chunk size includes the size of the header itself. */
|
||||||
|
if (pHeaderOut->sizeInBytes >= 24) {
|
||||||
|
pHeaderOut->sizeInBytes -= 24;
|
||||||
|
} else {
|
||||||
|
return DRWAV_INVALID_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
|
pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
|
||||||
*pRunningBytesReadOut += 24;
|
*pRunningBytesReadOut += 24;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2189,6 +2197,22 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
|
|
||||||
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
||||||
drwav_uint32 iSampleLoop;
|
drwav_uint32 iSampleLoop;
|
||||||
|
drwav_uint32 loopCount;
|
||||||
|
drwav_uint32 calculatedLoopCount;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When we calcualted the amount of memory required for the "smpl" chunk we excluded the chunk entirely
|
||||||
|
if the loop count in the header did not match with the calculated count based on the size of the
|
||||||
|
chunk. When this happens, the second stage will still hit this path but the `pMetadata` will be
|
||||||
|
non-null, but will either be pointing at the very end of the allocation or at the start of another
|
||||||
|
chunk. We need to check the loop counts for consistency *before* dereferencing the pMetadata object
|
||||||
|
so it's consistent with how we do it in the first stage.
|
||||||
|
*/
|
||||||
|
loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
|
||||||
|
calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
|
||||||
|
if (loopCount != calculatedLoopCount) {
|
||||||
|
return totalBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
pMetadata->type = drwav_metadata_type_smpl;
|
pMetadata->type = drwav_metadata_type_smpl;
|
||||||
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
||||||
|
|
@ -2205,7 +2229,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
The loop count needs to be validated against the size of the chunk for safety so we don't
|
The loop count needs to be validated against the size of the chunk for safety so we don't
|
||||||
attempt to read over the boundary of the chunk.
|
attempt to read over the boundary of the chunk.
|
||||||
*/
|
*/
|
||||||
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
|
if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) {
|
||||||
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
||||||
|
|
||||||
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
||||||
|
|
@ -2230,6 +2254,15 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||||
|
|
||||||
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
Getting here means the loop count in the header does not match up with the size of the
|
||||||
|
chunk. Clear out the data to zero just to be safe.
|
||||||
|
|
||||||
|
This should never actually get hit because we check for it above, but keeping this here
|
||||||
|
for added safety.
|
||||||
|
*/
|
||||||
|
DRWAV_ZERO_OBJECT(&pMetadata->data.smpl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2555,8 +2588,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_pars
|
||||||
pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
|
pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
|
||||||
DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
|
DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
|
||||||
|
|
||||||
bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
|
pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
|
||||||
pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory);
|
pMetadata->data.bext.pCodingHistory[pMetadata->data.bext.codingHistorySize] = '\0'; /* <-- Explicit null terminator in case of a badly formed file. */
|
||||||
|
|
||||||
|
bytesRead += pMetadata->data.bext.codingHistorySize;
|
||||||
} else {
|
} else {
|
||||||
pMetadata->data.bext.pCodingHistory = NULL;
|
pMetadata->data.bext.pCodingHistory = NULL;
|
||||||
pMetadata->data.bext.codingHistorySize = 0;
|
pMetadata->data.bext.codingHistorySize = 0;
|
||||||
|
|
@ -2730,10 +2765,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
|
||||||
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
|
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
|
||||||
if (bytesJustRead == sizeof(buffer)) {
|
if (bytesJustRead == sizeof(buffer)) {
|
||||||
drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
|
drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
|
||||||
drwav_uint64 calculatedLoopCount;
|
drwav_uint32 calculatedLoopCount;
|
||||||
|
|
||||||
/* The loop count must be validated against the size of the chunk. */
|
/* The loop count must be validated against the size of the chunk. */
|
||||||
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
|
calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
|
||||||
if (calculatedLoopCount == loopCount) {
|
if (calculatedLoopCount == loopCount) {
|
||||||
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
|
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
|
||||||
if (bytesJustRead == sizeof(buffer)) {
|
if (bytesJustRead == sizeof(buffer)) {
|
||||||
|
|
@ -2835,7 +2870,9 @@ 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 + 1; /* Coding history. */
|
|
||||||
|
/* Coding history. */
|
||||||
|
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1;
|
||||||
|
|
||||||
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
|
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
|
||||||
|
|
||||||
|
|
@ -3296,6 +3333,10 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
||||||
((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
|
||||||
drwav_uint8 fmtData[16];
|
drwav_uint8 fmtData[16];
|
||||||
|
|
||||||
|
if (header.sizeInBytes < sizeof(fmtData)) {
|
||||||
|
return DRWAV_FALSE; /* Invalid fmt chunk. */
|
||||||
|
}
|
||||||
|
|
||||||
foundChunk_fmt = DRWAV_TRUE;
|
foundChunk_fmt = DRWAV_TRUE;
|
||||||
|
|
||||||
if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
|
if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
|
||||||
|
|
@ -3808,6 +3849,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
||||||
|
|
||||||
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
|
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
|
||||||
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
|
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
|
||||||
|
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
|
||||||
|
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
|
||||||
|
return DRWAV_FALSE; /* Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
|
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
|
||||||
}
|
}
|
||||||
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
|
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
|
||||||
|
|
@ -3821,6 +3867,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
||||||
|
|
||||||
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
|
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
|
||||||
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
|
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
|
||||||
|
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
|
||||||
|
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
|
||||||
|
return DRWAV_FALSE; /* Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
|
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
|
||||||
|
|
||||||
/* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
|
/* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
|
||||||
|
|
@ -5285,7 +5336,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pC
|
||||||
DRWAV_ASSERT(pFileStdio != NULL);
|
DRWAV_ASSERT(pFileStdio != NULL);
|
||||||
DRWAV_ASSERT(pCursor != NULL);
|
DRWAV_ASSERT(pCursor != NULL);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(NXDK)
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
result = _ftelli64(pFileStdio);
|
result = _ftelli64(pFileStdio);
|
||||||
#else
|
#else
|
||||||
|
|
@ -5492,8 +5543,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, dr
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
newCursor = pWav->memoryStream.currentReadPos;
|
|
||||||
|
|
||||||
if (origin == DRWAV_SEEK_SET) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRWAV_SEEK_CUR) {
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
|
@ -5566,8 +5615,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
newCursor = pWav->memoryStreamWrite.currentWritePos;
|
|
||||||
|
|
||||||
if (origin == DRWAV_SEEK_SET) {
|
if (origin == DRWAV_SEEK_SET) {
|
||||||
newCursor = 0;
|
newCursor = 0;
|
||||||
} else if (origin == DRWAV_SEEK_CUR) {
|
} else if (origin == DRWAV_SEEK_CUR) {
|
||||||
|
|
@ -5576,7 +5623,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||||
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
||||||
} else {
|
} else {
|
||||||
DRWAV_ASSERT(!"Invalid seek origin");
|
DRWAV_ASSERT(!"Invalid seek origin");
|
||||||
return DRWAV_INVALID_ARGS;
|
return DRWAV_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
newCursor += offset;
|
newCursor += offset;
|
||||||
|
|
@ -6258,12 +6305,12 @@ 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[] = {
|
static const drwav_int32 adaptationTable[] = {
|
||||||
230, 230, 230, 230, 307, 409, 512, 614,
|
230, 230, 230, 230, 307, 409, 512, 614,
|
||||||
768, 614, 512, 409, 307, 230, 230, 230
|
768, 614, 512, 409, 307, 230, 230, 230
|
||||||
};
|
};
|
||||||
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
static const drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||||
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
static const 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);
|
||||||
|
|
@ -6292,7 +6339,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
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. */
|
/* 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)) {
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
return totalFramesRead; /* Invalid file. */
|
return totalFramesRead; /* Invalid file. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -6319,7 +6366,8 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
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. */
|
/* 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)) {
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table) ||
|
||||||
|
pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||||
return totalFramesRead; /* Invalid file. */
|
return totalFramesRead; /* Invalid file. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6373,14 +6421,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
drwav_int32 newSample0;
|
drwav_int32 newSample0;
|
||||||
drwav_int32 newSample1;
|
drwav_int32 newSample1;
|
||||||
|
|
||||||
|
/* The predictor is read from the file and then indexed into a table. Check that it's in bounds. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead;
|
||||||
|
}
|
||||||
|
|
||||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||||
|
|
@ -6390,15 +6440,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
||||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
||||||
|
|
||||||
|
|
||||||
pWav->msadpcm.cachedFrames[2] = newSample0;
|
pWav->msadpcm.cachedFrames[2] = newSample0;
|
||||||
pWav->msadpcm.cachedFrames[3] = newSample1;
|
pWav->msadpcm.cachedFrames[3] = newSample1;
|
||||||
pWav->msadpcm.cachedFrameCount = 2;
|
pWav->msadpcm.cachedFrameCount = 2;
|
||||||
|
|
@ -6408,28 +6454,30 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||||
drwav_int32 newSample1;
|
drwav_int32 newSample1;
|
||||||
|
|
||||||
/* Left. */
|
/* Left. */
|
||||||
|
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[0] < 16) {
|
|
||||||
pWav->msadpcm.delta[0] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||||
|
|
||||||
|
|
||||||
/* Right. */
|
/* Right. */
|
||||||
|
if (pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||||
|
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||||
|
}
|
||||||
|
|
||||||
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
||||||
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
||||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||||
|
|
||||||
pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
|
pWav->msadpcm.delta[1] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF);
|
||||||
if (pWav->msadpcm.delta[1] < 16) {
|
|
||||||
pWav->msadpcm.delta[1] = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
||||||
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
||||||
|
|
@ -6451,12 +6499,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||||
drwav_uint64 totalFramesRead = 0;
|
drwav_uint64 totalFramesRead = 0;
|
||||||
drwav_uint32 iChannel;
|
drwav_uint32 iChannel;
|
||||||
|
|
||||||
static drwav_int32 indexTable[16] = {
|
static const drwav_int32 indexTable[16] = {
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8
|
-1, -1, -1, -1, 2, 4, 6, 8
|
||||||
};
|
};
|
||||||
|
|
||||||
static drwav_int32 stepTable[89] = {
|
static const drwav_int32 stepTable[89] = {
|
||||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||||
|
|
@ -6606,7 +6654,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||||
|
|
||||||
|
|
||||||
#ifndef DR_WAV_NO_CONVERSION_API
|
#ifndef DR_WAV_NO_CONVERSION_API
|
||||||
static unsigned short g_drwavAlawTable[256] = {
|
static const unsigned short g_drwavAlawTable[256] = {
|
||||||
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
||||||
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
||||||
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
||||||
|
|
@ -6625,7 +6673,7 @@ static unsigned short g_drwavAlawTable[256] = {
|
||||||
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short g_drwavMulawTable[256] = {
|
static const unsigned short g_drwavMulawTable[256] = {
|
||||||
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
||||||
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
||||||
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
||||||
|
|
@ -6703,6 +6751,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn,
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!drwav__is_little_endian()) {
|
||||||
|
sample = drwav__bswap64(sample);
|
||||||
|
}
|
||||||
|
|
||||||
pIn += j;
|
pIn += j;
|
||||||
*pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
|
*pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
|
||||||
}
|
}
|
||||||
|
|
@ -7144,6 +7196,10 @@ DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!drwav__is_little_endian()) {
|
||||||
|
sample = drwav__bswap64(sample);
|
||||||
|
}
|
||||||
|
|
||||||
pIn += j;
|
pIn += j;
|
||||||
*pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
|
*pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
|
||||||
}
|
}
|
||||||
|
|
@ -7628,6 +7684,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn,
|
||||||
shift += 8;
|
shift += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!drwav__is_little_endian()) {
|
||||||
|
sample = drwav__bswap64(sample);
|
||||||
|
}
|
||||||
|
|
||||||
pIn += j;
|
pIn += j;
|
||||||
*pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
|
*pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
|
||||||
}
|
}
|
||||||
|
|
@ -8053,6 +8113,12 @@ DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, uns
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int16)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8095,6 +8161,12 @@ DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(float)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8137,6 +8209,12 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns
|
||||||
|
|
||||||
DRWAV_ASSERT(pWav != NULL);
|
DRWAV_ASSERT(pWav != NULL);
|
||||||
|
|
||||||
|
/* Check for overflow before multiplication. */
|
||||||
|
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int32)) {
|
||||||
|
drwav_uninit(pWav);
|
||||||
|
return NULL; /* Overflow or invalid channels. */
|
||||||
|
}
|
||||||
|
|
||||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
||||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||||
drwav_uninit(pWav);
|
drwav_uninit(pWav);
|
||||||
|
|
@ -8517,7 +8595,31 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.14.0 - TBD
|
v0.14.6 - TBD
|
||||||
|
- Fix an error when loading files with a malformed "bext" chunk.
|
||||||
|
- Fix an error when loading files with a malformed "fmt" chunk.
|
||||||
|
- Fix an underflow error with badly formed ADPCM encoded files.
|
||||||
|
- Fix an underflow error with badly formed W64 files.
|
||||||
|
- Fix an error when converting from >32 bit samples to s16/f32/s32 on big-endian architectures.
|
||||||
|
|
||||||
|
v0.14.5 - 2026-03-03
|
||||||
|
- Fix a crash when loading files with a malformed "smpl" chunk.
|
||||||
|
- Fix a signed overflow bug with the MS-ADPCM decoder.
|
||||||
|
|
||||||
|
v0.14.4 - 2026-01-17
|
||||||
|
- Fix some compilation warnings.
|
||||||
|
|
||||||
|
v0.14.3 - 2025-12-14
|
||||||
|
- Fix a possible out-of-bounds read when reading from MS-ADPCM encoded files.
|
||||||
|
- Fix a possible integer overflow error.
|
||||||
|
|
||||||
|
v0.14.2 - 2025-12-02
|
||||||
|
- Fix a compilation warning.
|
||||||
|
|
||||||
|
v0.14.1 - 2025-09-10
|
||||||
|
- Fix an error with the NXDK build.
|
||||||
|
|
||||||
|
v0.14.0 - 2025-07-23
|
||||||
- API CHANGE: Seek origin enums have been renamed to the following:
|
- API CHANGE: Seek origin enums have been renamed to the following:
|
||||||
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
||||||
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
||||||
|
|
|
||||||
4
src/external/jar_mod.h
vendored
4
src/external/jar_mod.h
vendored
|
|
@ -1538,10 +1538,10 @@ mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename)
|
||||||
modctx->modfile = (muchar *) JARMOD_MALLOC(fsize);
|
modctx->modfile = (muchar *) JARMOD_MALLOC(fsize);
|
||||||
modctx->modfilesize = fsize;
|
modctx->modfilesize = fsize;
|
||||||
memset(modctx->modfile, 0, fsize);
|
memset(modctx->modfile, 0, fsize);
|
||||||
fread(modctx->modfile, fsize, 1, f);
|
if(fread(modctx->modfile, fsize, 1, f) != 1) fsize = 0;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if(!jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0;
|
if(fsize && !jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0;
|
||||||
} else fsize = 0;
|
} else fsize = 0;
|
||||||
}
|
}
|
||||||
return fsize;
|
return fsize;
|
||||||
|
|
|
||||||
53
src/external/m3d.h
vendored
53
src/external/m3d.h
vendored
|
|
@ -236,7 +236,8 @@ typedef struct {
|
||||||
#ifdef M3D_ASCII
|
#ifdef M3D_ASCII
|
||||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
||||||
char *key;
|
char *key;
|
||||||
#else
|
#endif
|
||||||
|
#ifndef M3D_ASCII
|
||||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
||||||
#endif
|
#endif
|
||||||
} m3dpd_t;
|
} m3dpd_t;
|
||||||
|
|
@ -414,7 +415,8 @@ typedef struct {
|
||||||
#ifdef M3D_ASCII
|
#ifdef M3D_ASCII
|
||||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||||
char *key;
|
char *key;
|
||||||
#else
|
#endif
|
||||||
|
#ifndef M3D_ASCII
|
||||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||||
#endif
|
#endif
|
||||||
uint8_t p;
|
uint8_t p;
|
||||||
|
|
@ -674,6 +676,10 @@ static m3dcd_t m3d_commandtypes[] = {
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/* we'll need this with M3D_NOTEXTURE */
|
||||||
|
char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
||||||
|
|
||||||
|
#ifndef M3D_NOTEXTURE
|
||||||
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
||||||
/* PNG decompressor from
|
/* PNG decompressor from
|
||||||
|
|
||||||
|
|
@ -1868,6 +1874,11 @@ static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp,
|
||||||
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
||||||
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(STBI_INCLUDE_STB_IMAGE_H) || defined(STBI_NO_ZLIB)
|
||||||
|
#error "stb_image.h not included or STBI_NO_ZLIB defined. Sorry, we need its zlib implementation for proper integration"
|
||||||
|
#endif
|
||||||
|
#endif /* M3D_NOTEXTURE */
|
||||||
|
|
||||||
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
||||||
/* zlib_compressor from
|
/* zlib_compressor from
|
||||||
|
|
@ -2168,9 +2179,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
unsigned int i, len = 0;
|
unsigned int i, len = 0;
|
||||||
unsigned char *buff = NULL;
|
unsigned char *buff = NULL;
|
||||||
char *fn2;
|
char *fn2;
|
||||||
|
#ifndef M3D_NOTEXTURE
|
||||||
unsigned int w, h;
|
unsigned int w, h;
|
||||||
stbi__context s;
|
stbi__context s;
|
||||||
stbi__result_info ri;
|
stbi__result_info ri;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* failsafe */
|
/* failsafe */
|
||||||
if(!fn || !*fn) return M3D_UNDEF;
|
if(!fn || !*fn) return M3D_UNDEF;
|
||||||
|
|
@ -2209,13 +2222,17 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
if(!model->texture) {
|
if(!model->texture) {
|
||||||
if(buff && freecb) (*freecb)(buff);
|
if(buff && freecb) (*freecb)(buff);
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
model->numtexture = 0;
|
||||||
return M3D_UNDEF;
|
return M3D_UNDEF;
|
||||||
}
|
}
|
||||||
|
memset(&model->texture[i], 0, sizeof(m3dtx_t));
|
||||||
model->texture[i].name = fn;
|
model->texture[i].name = fn;
|
||||||
model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL;
|
|
||||||
if(buff) {
|
if(buff) {
|
||||||
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
||||||
s.read_from_callbacks = 0;
|
#ifndef M3D_NOTEXTURE
|
||||||
|
/* return pixel buffer of the decoded texture */
|
||||||
|
memset(&s, 0, sizeof(s));
|
||||||
|
memset(&ri, 0, sizeof(ri));
|
||||||
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
||||||
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
||||||
/* don't use model->texture[i].w directly, it's a uint16_t */
|
/* don't use model->texture[i].w directly, it's a uint16_t */
|
||||||
|
|
@ -2225,6 +2242,16 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||||
model->texture[i].w = w;
|
model->texture[i].w = w;
|
||||||
model->texture[i].h = h;
|
model->texture[i].h = h;
|
||||||
model->texture[i].f = (uint8_t)len;
|
model->texture[i].f = (uint8_t)len;
|
||||||
|
#else
|
||||||
|
/* return only the raw undecoded texture */
|
||||||
|
if((model->texture[i].d = (uint8_t*)M3D_MALLOC(len))) {
|
||||||
|
memcpy(model->texture[i].d, buff, len);
|
||||||
|
model->texture[i].w = len & 0xffff;
|
||||||
|
model->texture[i].h = (len >> 16) & 0xffff;
|
||||||
|
model->texture[i].f = 0;
|
||||||
|
} else
|
||||||
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef M3D_TX_INTERP
|
#ifdef M3D_TX_INTERP
|
||||||
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
||||||
|
|
@ -4280,7 +4307,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec)
|
||||||
if(l != msec) {
|
if(l != msec) {
|
||||||
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
||||||
if(!model->vertex) {
|
if(!model->vertex) {
|
||||||
free(ret);
|
M3D_FREE(ret);
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -4492,7 +4519,7 @@ void m3d_free(m3d_t *model)
|
||||||
if(model->label) M3D_FREE(model->label);
|
if(model->label) M3D_FREE(model->label);
|
||||||
if(model->inlined) M3D_FREE(model->inlined);
|
if(model->inlined) M3D_FREE(model->inlined);
|
||||||
if(model->extra) M3D_FREE(model->extra);
|
if(model->extra) M3D_FREE(model->extra);
|
||||||
free(model);
|
M3D_FREE(model);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -4568,15 +4595,15 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s)
|
||||||
safe = _m3d_safestr(s, 0);
|
safe = _m3d_safestr(s, 0);
|
||||||
if(!safe) return 0;
|
if(!safe) return 0;
|
||||||
if(!*safe) {
|
if(!*safe) {
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(i = 0; i < numstr; i++)
|
for(i = 0; i < numstr; i++)
|
||||||
if(!strcmp(str[i].str, s)) {
|
if(!strcmp(str[i].str, s)) {
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
return str[i].offs;
|
return str[i].offs;
|
||||||
}
|
}
|
||||||
free(safe);
|
M3D_FREE(safe);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4889,7 +4916,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||||
if(cmd->type == m3dc_mesh) {
|
if(cmd->type == m3dc_mesh) {
|
||||||
if(numgrp + 2 < maxgrp) {
|
if(numgrp + 2 < maxgrp) {
|
||||||
maxgrp += 1024;
|
maxgrp += 1024;
|
||||||
grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t));
|
grpidx = (uint32_t*)M3D_REALLOC(grpidx, maxgrp * sizeof(uint32_t));
|
||||||
if(!grpidx) goto memerr;
|
if(!grpidx) goto memerr;
|
||||||
if(!numgrp) {
|
if(!numgrp) {
|
||||||
grpidx[0] = 0;
|
grpidx[0] = 0;
|
||||||
|
|
@ -5194,7 +5221,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||||
if(sa) M3D_FREE(sa);
|
if(sa) M3D_FREE(sa);
|
||||||
if(sd) M3D_FREE(sd);
|
if(sd) M3D_FREE(sd);
|
||||||
if(out) M3D_FREE(out);
|
if(out) M3D_FREE(out);
|
||||||
if(opa) free(opa);
|
if(opa) M3D_FREE(opa);
|
||||||
if(h) M3D_FREE(h);
|
if(h) M3D_FREE(h);
|
||||||
M3D_LOG("Out of memory");
|
M3D_LOG("Out of memory");
|
||||||
model->errcode = M3D_ERR_ALLOC;
|
model->errcode = M3D_ERR_ALLOC;
|
||||||
|
|
@ -6285,7 +6312,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||||
if(skin) M3D_FREE(skin);
|
if(skin) M3D_FREE(skin);
|
||||||
if(str) M3D_FREE(str);
|
if(str) M3D_FREE(str);
|
||||||
if(vrtx) M3D_FREE(vrtx);
|
if(vrtx) M3D_FREE(vrtx);
|
||||||
if(opa) free(opa);
|
if(opa) M3D_FREE(opa);
|
||||||
if(h) M3D_FREE(h);
|
if(h) M3D_FREE(h);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
@ -6310,7 +6337,7 @@ namespace M3D {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Model() {
|
Model() {
|
||||||
this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
this->model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||||
}
|
}
|
||||||
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
||||||
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
||||||
|
|
|
||||||
10
src/external/qoa.h
vendored
10
src/external/qoa.h
vendored
|
|
@ -387,7 +387,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||||
int slice_start = sample_index * channels + c;
|
int slice_start = sample_index * channels + c;
|
||||||
int slice_end = (sample_index + slice_len) * channels + c;
|
int slice_end = (sample_index + slice_len) * channels + c;
|
||||||
|
|
||||||
/* Brute for search for the best scalefactor. Just go through all
|
/* Brute force search for the best scalefactor. Just go through all
|
||||||
16 scalefactors, encode all samples for the current slice and
|
16 scalefactors, encode all samples for the current slice and
|
||||||
meassure the total squared error. */
|
meassure the total squared error. */
|
||||||
qoa_uint64_t best_rank = -1;
|
qoa_uint64_t best_rank = -1;
|
||||||
|
|
@ -402,7 +402,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||||
/* There is a strong correlation between the scalefactors of
|
/* There is a strong correlation between the scalefactors of
|
||||||
neighboring slices. As an optimization, start testing
|
neighboring slices. As an optimization, start testing
|
||||||
the best scalefactor of the previous slice first. */
|
the best scalefactor of the previous slice first. */
|
||||||
int scalefactor = (sfi + prev_scalefactor[c]) % 16;
|
int scalefactor = (sfi + prev_scalefactor[c]) & (16 - 1);
|
||||||
|
|
||||||
/* We have to reset the LMS state to the last known good one
|
/* We have to reset the LMS state to the last known good one
|
||||||
before trying each scalefactor, as each pass updates the LMS
|
before trying each scalefactor, as each pass updates the LMS
|
||||||
|
|
@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
|
||||||
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
||||||
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
||||||
|
|
||||||
unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size);
|
unsigned char *bytes = QOA_MALLOC(encoded_size);
|
||||||
|
|
||||||
for (unsigned int c = 0; c < qoa->channels; c++) {
|
for (unsigned int c = 0; c < qoa->channels; c++) {
|
||||||
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
||||||
|
|
@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) {
|
||||||
|
|
||||||
/* Calculate the required size of the sample buffer and allocate */
|
/* Calculate the required size of the sample buffer and allocate */
|
||||||
int total_samples = qoa->samples * qoa->channels;
|
int total_samples = qoa->samples * qoa->channels;
|
||||||
short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short));
|
short *sample_data = QOA_MALLOC(total_samples * sizeof(short));
|
||||||
|
|
||||||
unsigned int sample_index = 0;
|
unsigned int sample_index = 0;
|
||||||
unsigned int frame_len;
|
unsigned int frame_len;
|
||||||
|
|
@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) {
|
||||||
bytes_read = fread(data, 1, size, f);
|
bytes_read = fread(data, 1, size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa);
|
sample_data = qoa_decode(data, bytes_read, qoa);
|
||||||
QOA_FREE(data);
|
QOA_FREE(data);
|
||||||
return sample_data;
|
return sample_data;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/external/qoi.h
vendored
4
src/external/qoi.h
vendored
|
|
@ -427,7 +427,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
||||||
run = 0;
|
run = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
index_pos = QOI_COLOR_HASH(px) & (64 - 1);
|
||||||
|
|
||||||
if (index[index_pos].v == px.v) {
|
if (index[index_pos].v == px.v) {
|
||||||
bytes[p++] = QOI_OP_INDEX | index_pos;
|
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||||
|
|
@ -574,7 +574,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
||||||
run = (b1 & 0x3f);
|
run = (b1 & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
index[QOI_COLOR_HASH(px) & (64 - 1)] = px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels[px_pos + 0] = px.rgba.r;
|
pixels[px_pos + 0] = px.rgba.r;
|
||||||
|
|
|
||||||
187
src/external/rlsw.h
vendored
187
src/external/rlsw.h
vendored
|
|
@ -153,7 +153,7 @@
|
||||||
#define SW_MAX_TEXTURES 128
|
#define SW_MAX_TEXTURES 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enables the use of a lookup table for uint8_t to float conversion
|
// Enable the use of a lookup table for uint8_t to float conversion
|
||||||
// Requires an additional 1KB of global memory
|
// Requires an additional 1KB of global memory
|
||||||
// Disabled when SIMD intrinsics are enabled
|
// Disabled when SIMD intrinsics are enabled
|
||||||
#ifndef SW_USE_COLOR_LUT
|
#ifndef SW_USE_COLOR_LUT
|
||||||
|
|
@ -164,6 +164,19 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Fast power-of-two texture wrap (SW_REPEAT mode only)
|
||||||
|
// When defined, textures whose width/height are powers of two use a bitmask
|
||||||
|
// wrap (`x & (size-1)`) instead of `floorf`-based fractional wrap or the
|
||||||
|
// signed `%` chain in the linear sampler. Saves a software divide on Xtensa
|
||||||
|
// and a few instructions everywhere. NPOT textures keep using the original
|
||||||
|
// path via a runtime `(size & (size-1)) == 0` check, so SW_REPEAT remains
|
||||||
|
// correct for them. The only observable behavior change is for POT textures
|
||||||
|
// sampled with negative UV coordinates: bitmask wrap (two's complement) can
|
||||||
|
// differ from `sw_fract` by one texel. Off by default to keep bit-for-bit
|
||||||
|
// behavior; opt in if you control your asset UVs.
|
||||||
|
//
|
||||||
|
// #define SW_TEXTURE_REPEAT_POT_FAST
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// OpenGL Compatibility Types
|
// OpenGL Compatibility Types
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -200,6 +213,7 @@ typedef double GLclampd;
|
||||||
#define GL_RENDERER 0x1F01
|
#define GL_RENDERER 0x1F01
|
||||||
#define GL_VERSION 0x1F02
|
#define GL_VERSION 0x1F02
|
||||||
#define GL_EXTENSIONS 0x1F03
|
#define GL_EXTENSIONS 0x1F03
|
||||||
|
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||||
|
|
||||||
//#define GL_ATTRIB_STACK_DEPTH 0x0BB0
|
//#define GL_ATTRIB_STACK_DEPTH 0x0BB0
|
||||||
//#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
|
//#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
|
||||||
|
|
@ -507,6 +521,7 @@ typedef enum {
|
||||||
SW_RENDERER = GL_RENDERER,
|
SW_RENDERER = GL_RENDERER,
|
||||||
SW_VERSION = GL_VERSION,
|
SW_VERSION = GL_VERSION,
|
||||||
SW_EXTENSIONS = GL_EXTENSIONS,
|
SW_EXTENSIONS = GL_EXTENSIONS,
|
||||||
|
SW_SHADING_LANGUAGE_VERSION = GL_SHADING_LANGUAGE_VERSION,
|
||||||
SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE,
|
SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE,
|
||||||
SW_DEPTH_CLEAR_VALUE = GL_DEPTH_CLEAR_VALUE,
|
SW_DEPTH_CLEAR_VALUE = GL_DEPTH_CLEAR_VALUE,
|
||||||
SW_CURRENT_COLOR = GL_CURRENT_COLOR,
|
SW_CURRENT_COLOR = GL_CURRENT_COLOR,
|
||||||
|
|
@ -844,6 +859,17 @@ SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWatta
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ESP-DSP acceleration: ESP-IDF ships an optimized math library that includes
|
||||||
|
// `dspm_mult_4x4x4_f32` (4x4 matrix multiply) and `dspm_mult_4x4x1_f32`
|
||||||
|
// (matrix * vector). These are S3-tuned hand-vectorized kernels that beat the
|
||||||
|
// scalar versions for both throughput and code-size. Detection is opt-in to
|
||||||
|
// keep the dependency optional: define SW_USE_ESP_DSP from your build system
|
||||||
|
// (or rely on the `idf_component.yml` example shown in the rlsw docs).
|
||||||
|
#if defined(ESP_PLATFORM) && defined(SW_USE_ESP_DSP)
|
||||||
|
#define SW_HAS_ESP_DSP
|
||||||
|
#include "dspm_mult.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define SW_CURLY_INIT(name) name
|
#define SW_CURLY_INIT(name) name
|
||||||
#else
|
#else
|
||||||
|
|
@ -1038,6 +1064,9 @@ typedef struct {
|
||||||
SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION)
|
SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION)
|
||||||
sw_matrix_t *currentMatrix; // Pointer to the currently used matrix according to the mode
|
sw_matrix_t *currentMatrix; // Pointer to the currently used matrix according to the mode
|
||||||
sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally
|
sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally
|
||||||
|
#ifdef SW_HAS_ESP_DSP
|
||||||
|
float matMVP_rm[16]; // Row-major MVP, kept in sync for esp-dsp dspm_mult_4x4x1_f32 vertex transform
|
||||||
|
#endif
|
||||||
bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt
|
bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt
|
||||||
|
|
||||||
sw_handle_t boundFramebufferId; // Framebuffer currently bound
|
sw_handle_t boundFramebufferId; // Framebuffer currently bound
|
||||||
|
|
@ -1141,6 +1170,14 @@ static inline void sw_matrix_id(sw_matrix_t dst)
|
||||||
|
|
||||||
static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RESTRICT left, const float *SW_RESTRICT right)
|
static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RESTRICT left, const float *SW_RESTRICT right)
|
||||||
{
|
{
|
||||||
|
#ifdef SW_HAS_ESP_DSP
|
||||||
|
// dspm_mult_4x4x4_f32 treats its operands as row-major. rlsw stores matrices
|
||||||
|
// column-major, so passing them flat is equivalent to passing transposes:
|
||||||
|
// dspm_mult(L^T, R^T) computes (L^T)*(R^T) = (R*L)^T, written back into a
|
||||||
|
// flat array gives the same bit pattern as the column-major product (R*L)
|
||||||
|
// -- exactly the semantic the scalar fallback below has.
|
||||||
|
dspm_mult_4x4x4_f32(left, right, dst);
|
||||||
|
#else
|
||||||
float l00 = left[0], l01 = left[1], l02 = left[2], l03 = left[3];
|
float l00 = left[0], l01 = left[1], l02 = left[2], l03 = left[3];
|
||||||
float l10 = left[4], l11 = left[5], l12 = left[6], l13 = left[7];
|
float l10 = left[4], l11 = left[5], l12 = left[6], l13 = left[7];
|
||||||
float l20 = left[8], l21 = left[9], l22 = left[10], l23 = left[11];
|
float l20 = left[8], l21 = left[9], l22 = left[10], l23 = left[11];
|
||||||
|
|
@ -1165,6 +1202,7 @@ static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RES
|
||||||
dst[7] = l10*right[3] + l11*right[7] + l12*right[11] + l13*right[15];
|
dst[7] = l10*right[3] + l11*right[7] + l12*right[11] + l13*right[15];
|
||||||
dst[11] = l20*right[3] + l21*right[7] + l22*right[11] + l23*right[15];
|
dst[11] = l20*right[3] + l21*right[7] + l22*right[11] + l23*right[15];
|
||||||
dst[15] = l30*right[3] + l31*right[7] + l32*right[11] + l33*right[15];
|
dst[15] = l30*right[3] + l31*right[7] + l32*right[11] + l33*right[15];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right)
|
static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right)
|
||||||
|
|
@ -1210,6 +1248,33 @@ static inline float sw_fract(float x)
|
||||||
return (x - floorf(x));
|
return (x - floorf(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast reciprocal: 1-ULP accurate in ~7 instructions on Xtensa using the
|
||||||
|
// hardware `recip0.s` seed + two Newton-Raphson refinement steps. All work
|
||||||
|
// stays in FPU registers — no `__divsf3` software call. Hot-path divisions
|
||||||
|
// in the rasterizer (span/triangle setup, perspective divide, etc.) call
|
||||||
|
// this. On non-Xtensa targets it transparently expands to `1.0f / x`, so
|
||||||
|
// generated code is identical to before.
|
||||||
|
#if defined(__XTENSA__)
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline float sw_rcp(float x)
|
||||||
|
{
|
||||||
|
float result, temp;
|
||||||
|
__asm__(
|
||||||
|
"recip0.s %0, %2\n"
|
||||||
|
"const.s %1, 1\n"
|
||||||
|
"msub.s %1, %2, %0\n"
|
||||||
|
"madd.s %0, %0, %1\n"
|
||||||
|
"const.s %1, 1\n"
|
||||||
|
"msub.s %1, %2, %0\n"
|
||||||
|
"maddn.s %0, %0, %1\n"
|
||||||
|
: "=&f"(result), "=&f"(temp) : "f"(x)
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline float sw_rcp(float x) { return 1.0f/x; }
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline uint8_t sw_luminance8(const uint8_t *color)
|
static inline uint8_t sw_luminance8(const uint8_t *color)
|
||||||
{
|
{
|
||||||
return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8);
|
return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8);
|
||||||
|
|
@ -2357,7 +2422,8 @@ static inline bool sw_texture_alloc(sw_texture_t *texture, const void *data, int
|
||||||
|
|
||||||
sw_pixel_read_color8_f readColor8 = NULL;
|
sw_pixel_read_color8_f readColor8 = NULL;
|
||||||
sw_pixel_read_color_f readColor = NULL;
|
sw_pixel_read_color_f readColor = NULL;
|
||||||
if (!isDepth) {
|
if (!isDepth)
|
||||||
|
{
|
||||||
readColor8 = sw_pixel_get_read_color8_func(format);
|
readColor8 = sw_pixel_get_read_color8_func(format);
|
||||||
readColor = sw_pixel_get_read_color_func(format);
|
readColor = sw_pixel_get_read_color_func(format);
|
||||||
}
|
}
|
||||||
|
|
@ -2405,18 +2471,38 @@ static inline void sw_texture_free(sw_texture_t *texture)
|
||||||
|
|
||||||
static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
|
static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
|
||||||
{
|
{
|
||||||
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
|
int x, y;
|
||||||
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
|
|
||||||
|
|
||||||
int x = u*tex->width;
|
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||||
int y = v*tex->height;
|
if ((tex->sWrap == SW_REPEAT) && ((tex->width & tex->wMinus1) == 0))
|
||||||
|
{
|
||||||
|
x = (int)(u*tex->width) & tex->wMinus1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
|
||||||
|
x = (int)(u*tex->width);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||||
|
if ((tex->tWrap == SW_REPEAT) && ((tex->height & tex->hMinus1) == 0))
|
||||||
|
{
|
||||||
|
y = (int)(v*tex->height) & tex->hMinus1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
|
||||||
|
y = (int)(v*tex->height);
|
||||||
|
}
|
||||||
|
|
||||||
tex->readColor(color, tex->pixels, y*tex->width + x);
|
tex->readColor(color, tex->pixels, y*tex->width + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
|
static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
|
||||||
{
|
{
|
||||||
// TODO: With a bit more cleverness thee number of operations can
|
// TODO: With a bit more cleverness the number of operations can
|
||||||
// be clearly reduced, but for now it works fine
|
// be clearly reduced, but for now it works fine
|
||||||
|
|
||||||
float xf = (u*tex->width) - 0.5f;
|
float xf = (u*tex->width) - 0.5f;
|
||||||
|
|
@ -2431,13 +2517,19 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t
|
||||||
int x1 = x0 + 1;
|
int x1 = x0 + 1;
|
||||||
int y1 = y0 + 1;
|
int y1 = y0 + 1;
|
||||||
|
|
||||||
// NOTE: If the textures are POT, avoid the division for SW_REPEAT
|
|
||||||
|
|
||||||
if (tex->sWrap == SW_CLAMP)
|
if (tex->sWrap == SW_CLAMP)
|
||||||
{
|
{
|
||||||
x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0;
|
x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0;
|
||||||
x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1;
|
x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1;
|
||||||
}
|
}
|
||||||
|
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||||
|
else if ((tex->width & tex->wMinus1) == 0)
|
||||||
|
{
|
||||||
|
// POT fast path: bitmask wrap covers negative ints via two's complement
|
||||||
|
x0 = x0 & tex->wMinus1;
|
||||||
|
x1 = x1 & tex->wMinus1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x0 = (x0%tex->width + tex->width)%tex->width;
|
x0 = (x0%tex->width + tex->width)%tex->width;
|
||||||
|
|
@ -2449,6 +2541,13 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t
|
||||||
y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0;
|
y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0;
|
||||||
y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1;
|
y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1;
|
||||||
}
|
}
|
||||||
|
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||||
|
else if ((tex->height & tex->hMinus1) == 0)
|
||||||
|
{
|
||||||
|
y0 = y0 & tex->hMinus1;
|
||||||
|
y1 = y1 & tex->hMinus1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
y0 = (y0%tex->height + tex->height)%tex->height;
|
y0 = (y0%tex->height + tex->height)%tex->height;
|
||||||
|
|
@ -2803,7 +2902,8 @@ static const sw_blend_f SW_BLEND_TABLE[SW_BLEND_FACTOR_COUNT][SW_BLEND_FACTOR_CO
|
||||||
// Maps a GL blend factor enum to its compact table index
|
// Maps a GL blend factor enum to its compact table index
|
||||||
static inline int sw_blend_factor_index(SWfactor f)
|
static inline int sw_blend_factor_index(SWfactor f)
|
||||||
{
|
{
|
||||||
switch (f) {
|
switch (f)
|
||||||
|
{
|
||||||
case SW_ZERO: return 0;
|
case SW_ZERO: return 0;
|
||||||
case SW_ONE: return 1;
|
case SW_ONE: return 1;
|
||||||
case SW_SRC_COLOR: return 2;
|
case SW_SRC_COLOR: return 2;
|
||||||
|
|
@ -2821,7 +2921,8 @@ static inline int sw_blend_factor_index(SWfactor f)
|
||||||
|
|
||||||
static bool sw_blend_factor_needs_alpha(SWfactor f)
|
static bool sw_blend_factor_needs_alpha(SWfactor f)
|
||||||
{
|
{
|
||||||
switch (f) {
|
switch (f)
|
||||||
|
{
|
||||||
case SW_SRC_ALPHA:
|
case SW_SRC_ALPHA:
|
||||||
case SW_ONE_MINUS_SRC_ALPHA:
|
case SW_ONE_MINUS_SRC_ALPHA:
|
||||||
case SW_DST_ALPHA:
|
case SW_DST_ALPHA:
|
||||||
|
|
@ -2829,6 +2930,7 @@ static bool sw_blend_factor_needs_alpha(SWfactor f)
|
||||||
case SW_SRC_ALPHA_SATURATE: return true;
|
case SW_SRC_ALPHA_SATURATE: return true;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3362,7 +3464,7 @@ static void sw_triangle_clip_and_project(void)
|
||||||
|
|
||||||
// Calculation of the reciprocal of W for normalization
|
// Calculation of the reciprocal of W for normalization
|
||||||
// as well as perspective-correct attributes
|
// as well as perspective-correct attributes
|
||||||
const float wRcp = 1.0f/v->position[3];
|
const float wRcp = sw_rcp(v->position[3]);
|
||||||
|
|
||||||
// Division of XYZ coordinates by weight
|
// Division of XYZ coordinates by weight
|
||||||
v->position[0] *= wRcp;
|
v->position[0] *= wRcp;
|
||||||
|
|
@ -3477,7 +3579,7 @@ static void sw_quad_clip_and_project(void)
|
||||||
|
|
||||||
// Calculation of the reciprocal of W for normalization
|
// Calculation of the reciprocal of W for normalization
|
||||||
// as well as perspective-correct attributes
|
// as well as perspective-correct attributes
|
||||||
const float wRcp = 1.0f/v->position[3];
|
const float wRcp = sw_rcp(v->position[3]);
|
||||||
|
|
||||||
// Division of XYZ coordinates by weight
|
// Division of XYZ coordinates by weight
|
||||||
v->position[0] *= wRcp;
|
v->position[0] *= wRcp;
|
||||||
|
|
@ -3655,8 +3757,8 @@ static bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1)
|
||||||
if (!sw_line_clip(v0, v1)) return false;
|
if (!sw_line_clip(v0, v1)) return false;
|
||||||
|
|
||||||
// Convert clip coordinates to NDC
|
// Convert clip coordinates to NDC
|
||||||
v0->position[3] = 1.0f/v0->position[3];
|
v0->position[3] = sw_rcp(v0->position[3]);
|
||||||
v1->position[3] = 1.0f/v1->position[3];
|
v1->position[3] = sw_rcp(v1->position[3]);
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
v0->position[i] *= v0->position[3];
|
v0->position[i] *= v0->position[3];
|
||||||
|
|
@ -3705,7 +3807,7 @@ static bool sw_point_clip_and_project(sw_vertex_t *v)
|
||||||
if ((v->position[i] < -v->position[3]) || (v->position[i] > v->position[3])) return false;
|
if ((v->position[i] < -v->position[3]) || (v->position[i] > v->position[3])) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
v->position[3] = 1.0f/v->position[3];
|
v->position[3] = sw_rcp(v->position[3]);
|
||||||
v->position[0] *= v->position[3];
|
v->position[0] *= v->position[3];
|
||||||
v->position[1] *= v->position[3];
|
v->position[1] *= v->position[3];
|
||||||
v->position[2] *= v->position[3];
|
v->position[2] *= v->position[3];
|
||||||
|
|
@ -3787,6 +3889,19 @@ static void sw_immediate_begin(SWdraw mode)
|
||||||
RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
|
RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
|
||||||
RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
|
RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
|
||||||
|
|
||||||
|
#ifdef SW_HAS_ESP_DSP
|
||||||
|
// Pre-transpose to row-major so dspm_mult_4x4x1_f32(matMVP_rm, v, out)
|
||||||
|
// computes M*v directly in the per-vertex hot path. 16 scalar copies
|
||||||
|
// per MVP update vs. saving ~20 cycles per vertex transform.
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
RLSW.matMVP_rm[4*i + j] = RLSW.matMVP[4*j + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RLSW.isDirtyMVP = false;
|
RLSW.isDirtyMVP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3838,11 +3953,17 @@ static void sw_immediate_push_vertex(const float position[4])
|
||||||
sw_vertex_t *vertex = &RLSW.primitive.buffer[RLSW.primitive.vertexCount++];
|
sw_vertex_t *vertex = &RLSW.primitive.buffer[RLSW.primitive.vertexCount++];
|
||||||
|
|
||||||
// Calculate clip coordinates
|
// Calculate clip coordinates
|
||||||
|
#ifdef SW_HAS_ESP_DSP
|
||||||
|
// dspm_mult_4x4x1_f32 declares its inputs non-const; rlsw treats them as
|
||||||
|
// read-only and the cast is safe (the kernel only loads from B).
|
||||||
|
dspm_mult_4x4x1_f32(RLSW.matMVP_rm, (float *)position, vertex->position);
|
||||||
|
#else
|
||||||
const float *m = RLSW.matMVP;
|
const float *m = RLSW.matMVP;
|
||||||
vertex->position[0] = m[0]*position[0] + m[4]*position[1] + m[8]*position[2] + m[12]*position[3];
|
vertex->position[0] = m[0]*position[0] + m[4]*position[1] + m[8]*position[2] + m[12]*position[3];
|
||||||
vertex->position[1] = m[1]*position[0] + m[5]*position[1] + m[9]*position[2] + m[13]*position[3];
|
vertex->position[1] = m[1]*position[0] + m[5]*position[1] + m[9]*position[2] + m[13]*position[3];
|
||||||
vertex->position[2] = m[2]*position[0] + m[6]*position[1] + m[10]*position[2] + m[14]*position[3];
|
vertex->position[2] = m[2]*position[0] + m[6]*position[1] + m[10]*position[2] + m[14]*position[3];
|
||||||
vertex->position[3] = m[3]*position[0] + m[7]*position[1] + m[11]*position[2] + m[15]*position[3];
|
vertex->position[3] = m[3]*position[0] + m[7]*position[1] + m[11]*position[2] + m[15]*position[3];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy the attributes in the current vertex
|
// Copy the attributes in the current vertex
|
||||||
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
|
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
|
||||||
|
|
@ -4160,6 +4281,7 @@ const char *swGetString(SWget name)
|
||||||
case SW_RENDERER: result = "RLSW OpenGL Software Renderer"; break;
|
case SW_RENDERER: result = "RLSW OpenGL Software Renderer"; break;
|
||||||
case SW_VERSION: result = RLSW_VERSION; break;
|
case SW_VERSION: result = RLSW_VERSION; break;
|
||||||
case SW_EXTENSIONS: result = "None"; break;
|
case SW_EXTENSIONS: result = "None"; break;
|
||||||
|
case SW_SHADING_LANGUAGE_VERSION: result = "Not supported"; break;
|
||||||
default: RLSW.errCode = SW_INVALID_ENUM; break;
|
default: RLSW.errCode = SW_INVALID_ENUM; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5268,7 +5390,7 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||||
if (xStart == xEnd) return;
|
if (xStart == xEnd) return;
|
||||||
|
|
||||||
// Compute the inverse horizontal distance along the X axis
|
// Compute the inverse horizontal distance along the X axis
|
||||||
float dxRcp = 1.0f/(end->position[0] - start->position[0]);
|
float dxRcp = sw_rcp(end->position[0] - start->position[0]);
|
||||||
|
|
||||||
// Compute the interpolation steps along the X axis
|
// Compute the interpolation steps along the X axis
|
||||||
float dWdx = (end->position[3] - start->position[3])*dxRcp;
|
float dWdx = (end->position[3] - start->position[3])*dxRcp;
|
||||||
|
|
@ -5322,12 +5444,12 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||||
int blockEnd = x + SW_AFFINE_BLOCK;
|
int blockEnd = x + SW_AFFINE_BLOCK;
|
||||||
if (blockEnd > xEnd) blockEnd = xEnd;
|
if (blockEnd > xEnd) blockEnd = xEnd;
|
||||||
float blockLenF = (float)(blockEnd - x);
|
float blockLenF = (float)(blockEnd - x);
|
||||||
float blockLenRcp = 1.0f/blockLenF;
|
float blockLenRcp = sw_rcp(blockLenF);
|
||||||
|
|
||||||
// Only 2 '1/w' here; none inside the pixel loop
|
// Only 2 '1/w' here; none inside the pixel loop
|
||||||
float wRcpA = 1.0f/w;
|
float wRcpA = sw_rcp(w);
|
||||||
float wB = w + dWdx*blockLenF;
|
float wB = w + dWdx*blockLenF;
|
||||||
float wRcpB = 1.0f/wB;
|
float wRcpB = sw_rcp(wB);
|
||||||
|
|
||||||
// Perspective-correct color at both block endpoints, then affine gradient
|
// Perspective-correct color at both block endpoints, then affine gradient
|
||||||
float srcColor[4] = {
|
float srcColor[4] = {
|
||||||
|
|
@ -5398,7 +5520,9 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
discard:
|
discard:
|
||||||
|
#endif
|
||||||
srcColor[0] += dSrcColordx[0];
|
srcColor[0] += dSrcColordx[0];
|
||||||
srcColor[1] += dSrcColordx[1];
|
srcColor[1] += dSrcColordx[1];
|
||||||
srcColor[2] += dSrcColordx[2];
|
srcColor[2] += dSrcColordx[2];
|
||||||
|
|
@ -5443,9 +5567,10 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
|
||||||
if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
|
if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
|
||||||
|
|
||||||
// Extracting coordinates from the sorted vertices
|
// Extracting coordinates from the sorted vertices
|
||||||
float x0 = v0->position[0], y0 = v0->position[1];
|
// Put x away for safe keeping. Only y is used right now. Silences warnings.
|
||||||
float x1 = v1->position[0], y1 = v1->position[1];
|
float y0 = v0->position[1];
|
||||||
float x2 = v2->position[0], y2 = v2->position[1];
|
float y1 = v1->position[1];
|
||||||
|
float y2 = v2->position[1];
|
||||||
|
|
||||||
// Compute height differences
|
// Compute height differences
|
||||||
float h02 = y2 - y0;
|
float h02 = y2 - y0;
|
||||||
|
|
@ -5455,9 +5580,9 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
|
||||||
if (h02 < 1e-6f) return;
|
if (h02 < 1e-6f) return;
|
||||||
|
|
||||||
// Inverse edge dy for per-edge dV/dy (scanline interpolation)
|
// Inverse edge dy for per-edge dV/dy (scanline interpolation)
|
||||||
float h02Rcp = 1.0f/h02;
|
float h02Rcp = sw_rcp(h02);
|
||||||
float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f;
|
float h01Rcp = (h01 > 1e-6f)? sw_rcp(h01) : 0.0f;
|
||||||
float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f;
|
float h12Rcp = (h12 > 1e-6f)? sw_rcp(h12) : 0.0f;
|
||||||
|
|
||||||
// Compute gradients for each side of the triangle
|
// Compute gradients for each side of the triangle
|
||||||
sw_vertex_t dVXdy02, dVXdy01, dVXdy12;
|
sw_vertex_t dVXdy02, dVXdy01, dVXdy12;
|
||||||
|
|
@ -5556,8 +5681,8 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||||
float h = (float)(yMax - yMin);
|
float h = (float)(yMax - yMin);
|
||||||
if ((w <= 0) || (h <= 0)) return;
|
if ((w <= 0) || (h <= 0)) return;
|
||||||
|
|
||||||
float wRcp = 1.0f/w;
|
float wRcp = sw_rcp(w);
|
||||||
float hRcp = 1.0f/h;
|
float hRcp = sw_rcp(h);
|
||||||
|
|
||||||
// Subpixel corrections
|
// Subpixel corrections
|
||||||
float xSubstep = 1.0f - sw_fract(tl->position[0]);
|
float xSubstep = 1.0f - sw_fract(tl->position[0]);
|
||||||
|
|
@ -5655,7 +5780,9 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
discard:
|
discard:
|
||||||
|
#endif
|
||||||
color[0] += dCdx[0];
|
color[0] += dCdx[0];
|
||||||
color[1] += dCdx[1];
|
color[1] += dCdx[1];
|
||||||
color[2] += dCdx[2];
|
color[2] += dCdx[2];
|
||||||
|
|
@ -5742,7 +5869,7 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1)
|
||||||
// Compute per pixel increments
|
// Compute per pixel increments
|
||||||
float xInc = dx/steps;
|
float xInc = dx/steps;
|
||||||
float yInc = dy/steps;
|
float yInc = dy/steps;
|
||||||
float stepRcp = 1.0f/steps;
|
float stepRcp = sw_rcp(steps);
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
float zInc = (v1->position[2] - v0->position[2])*stepRcp;
|
float zInc = (v1->position[2] - v0->position[2])*stepRcp;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -5808,7 +5935,9 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
discard:
|
discard:
|
||||||
|
#endif
|
||||||
x += xInc;
|
x += xInc;
|
||||||
y += yInc;
|
y += yInc;
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
|
|
|
||||||
654
src/external/stb_image_resize2.h
vendored
654
src/external/stb_image_resize2.h
vendored
File diff suppressed because it is too large
Load Diff
12
src/external/win32_clipboard.h
vendored
12
src/external/win32_clipboard.h
vendored
|
|
@ -4,14 +4,14 @@
|
||||||
|
|
||||||
#ifndef WIN32_CLIPBOARD_
|
#ifndef WIN32_CLIPBOARD_
|
||||||
#define WIN32_CLIPBOARD_
|
#define WIN32_CLIPBOARD_
|
||||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize);
|
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize);
|
||||||
#endif // WIN32_CLIPBOARD_
|
#endif // WIN32_CLIPBOARD_
|
||||||
|
|
||||||
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION
|
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <limits.h>
|
||||||
|
|
||||||
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
|
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
|
||||||
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
|
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
|
||||||
|
|
@ -213,7 +213,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih); // Get pixel data offset fr
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize)
|
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize)
|
||||||
{
|
{
|
||||||
unsigned char *bmpData = NULL;
|
unsigned char *bmpData = NULL;
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||||
*width = bmpInfoHeader->biWidth;
|
*width = bmpInfoHeader->biWidth;
|
||||||
*height = bmpInfoHeader->biHeight;
|
*height = bmpInfoHeader->biHeight;
|
||||||
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
||||||
if (clipDataSize >= sizeof(BITMAPINFOHEADER))
|
if ((clipDataSize >= sizeof(BITMAPINFOHEADER)) && (clipDataSize < INT_MAX))
|
||||||
{
|
{
|
||||||
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
||||||
|
|
||||||
|
|
@ -236,7 +236,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
||||||
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
||||||
*dataSize = bmpFileSize;
|
*dataSize = (unsigned int)bmpFileSize;
|
||||||
|
|
||||||
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
|
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
|
||||||
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
||||||
|
|
@ -254,7 +254,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "Clipboard data is malformed");
|
TRACELOG(LOG_WARNING, "Clipboard data is not supported (>2GB?)");
|
||||||
GlobalUnlock(clipHandle);
|
GlobalUnlock(clipHandle);
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -616,13 +616,13 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -656,7 +656,7 @@ double GetTime(void)
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
struct timespec ts = { 0 };
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||||
|
|
||||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||||
|
|
||||||
|
|
@ -1273,20 +1273,19 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
int32_t keycode = AKeyEvent_getKeyCode(event);
|
int32_t keycode = AKeyEvent_getKeyCode(event);
|
||||||
//int32_t AKeyEvent_getMetaState(event);
|
//int32_t AKeyEvent_getMetaState(event);
|
||||||
|
|
||||||
// Handle gamepad button presses and releases
|
// Handle gamepad button presses and releases. AOSP stamps the
|
||||||
// NOTE: Skip gamepad handling if this is a keyboard event, as some devices
|
// KEYBOARD source bit on every key event from a gamepad, so
|
||||||
// report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags
|
// discriminate on the keycode rather than gating on source bits.
|
||||||
if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
||||||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
|
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
|
||||||
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
|
{
|
||||||
|
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
||||||
|
|
||||||
|
if (button != GAMEPAD_BUTTON_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Assuming a single gamepad, "detected" on its input event
|
// Assuming a single gamepad, "detected" on its input event
|
||||||
CORE.Input.Gamepad.ready[0] = true;
|
CORE.Input.Gamepad.ready[0] = true;
|
||||||
|
|
||||||
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
|
||||||
|
|
||||||
if (button == GAMEPAD_BUTTON_UNKNOWN) return 1;
|
|
||||||
|
|
||||||
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
||||||
{
|
{
|
||||||
CORE.Input.Gamepad.currentButtonState[0][button] = 1;
|
CORE.Input.Gamepad.currentButtonState[0][button] = 1;
|
||||||
|
|
@ -1295,6 +1294,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||||
|
|
||||||
return 1; // Handled gamepad button
|
return 1; // Handled gamepad button
|
||||||
}
|
}
|
||||||
|
// Unknown keycode: fall through to the keyboard handler below.
|
||||||
|
}
|
||||||
|
|
||||||
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
|
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
|
||||||
if (key != KEY_NULL)
|
if (key != KEY_NULL)
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,12 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLFWwindow *handle; // GLFW window handle (graphic device)
|
GLFWwindow *handle; // GLFW window handle (graphic device)
|
||||||
|
#if defined(__linux__) && defined(_GLFW_X11)
|
||||||
|
// Local storage for the window handle returned by glfwGetX11Window
|
||||||
|
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
|
||||||
|
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
|
||||||
|
XID windowHandleX11;
|
||||||
|
#endif
|
||||||
} PlatformData;
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -755,12 +761,6 @@ void SetWindowFocused(void)
|
||||||
glfwFocusWindow(platform.handle);
|
glfwFocusWindow(platform.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__linux__) && defined(_GLFW_X11)
|
|
||||||
// Local storage for the window handle returned by glfwGetX11Window
|
|
||||||
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
|
|
||||||
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
|
|
||||||
static XID X11WindowHandle;
|
|
||||||
#endif
|
|
||||||
// Get native window handle
|
// Get native window handle
|
||||||
void *GetWindowHandle(void)
|
void *GetWindowHandle(void)
|
||||||
{
|
{
|
||||||
|
|
@ -778,17 +778,16 @@ void *GetWindowHandle(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
X11WindowHandle = glfwGetX11Window(platform.handle);
|
platform.windowHandleX11 = glfwGetX11Window(platform.handle);
|
||||||
return &X11WindowHandle;
|
return &platform.windowHandleX11;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return glfwGetWaylandWindow(platform.handle);
|
return glfwGetWaylandWindow(platform.handle);
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
// Store the window handle localy and return a pointer to the variable instead
|
// Store the window handle localy and return a pointer to the variable instead
|
||||||
// Reasoning detailed in the declaration of X11WindowHandle
|
platform.windowHandleX11 = glfwGetX11Window(platform.handle);
|
||||||
X11WindowHandle = glfwGetX11Window(platform.handle);
|
return &platform.windowHandleX11;
|
||||||
return &X11WindowHandle;
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
|
@ -1055,7 +1054,8 @@ Image GetClipboardImage(void)
|
||||||
|
|
||||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned long long int dataSize = 0;
|
|
||||||
|
unsigned int dataSize = 0;
|
||||||
void *bmpData = NULL;
|
void *bmpData = NULL;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
|
|
@ -1113,7 +1113,7 @@ Image GetClipboardImage(void)
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
||||||
#endif // defined(_WIN32)
|
#endif // _WIN32
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||||
|
|
@ -1129,7 +1129,7 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
|
|
@ -1137,7 +1137,7 @@ void HideCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
|
@ -1151,7 +1151,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorLocked = false;
|
CORE.Input.Mouse.cursorLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
// Reset mouse position within the window area before disabling cursor
|
// Reset mouse position within the window area before disabling cursor
|
||||||
|
|
|
||||||
331
src/platforms/rcore_desktop_rgfw.c
Executable file → Normal file
331
src/platforms/rcore_desktop_rgfw.c
Executable file → Normal file
|
|
@ -177,6 +177,13 @@ typedef struct {
|
||||||
RGFW_window *window; // Native display device (physical screen connection)
|
RGFW_window *window; // Native display device (physical screen connection)
|
||||||
RGFW_monitor *monitor;
|
RGFW_monitor *monitor;
|
||||||
mg_gamepads minigamepad;
|
mg_gamepads minigamepad;
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
RGFW_surface *surface;
|
||||||
|
u8 *surfacePixels;
|
||||||
|
i32 surfaceWidth;
|
||||||
|
i32 surfaceHeight;
|
||||||
|
#endif
|
||||||
} PlatformData;
|
} PlatformData;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -723,7 +730,7 @@ void SetWindowIcon(Image image)
|
||||||
TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
|
TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RGFW_window_setIcon(platform.window, (u8 *)image.data, image.width, image.height, 4);
|
RGFW_window_setIcon(platform.window, (u8 *)image.data, image.width, image.height, RGFW_formatRGBA8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set icon for window
|
// Set icon for window
|
||||||
|
|
@ -749,8 +756,8 @@ void SetWindowIcons(Image *images, int count)
|
||||||
if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i];
|
if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, smallIcon->width, smallIcon->height, 4, RGFW_iconWindow);
|
if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, smallIcon->width, smallIcon->height, RGFW_formatRGBA8, RGFW_iconWindow);
|
||||||
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, bigIcon->width, bigIcon->height, 4, RGFW_iconTaskbar);
|
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, bigIcon->width, bigIcon->height, RGFW_formatRGBA8, RGFW_iconTaskbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -821,6 +828,11 @@ void SetWindowSize(int width, int height)
|
||||||
CORE.Window.screen.height = height;
|
CORE.Window.screen.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CORE.Window.usingFbo)
|
||||||
|
{
|
||||||
|
SetupViewport(CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
|
}
|
||||||
|
|
||||||
RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height);
|
RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1012,15 +1024,15 @@ Image GetClipboardImage(void)
|
||||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
unsigned long long int dataSize = 0; // moved into _WIN32 scope until other platforms gain support
|
unsigned int dataSize = 0;
|
||||||
void *fileData = NULL; // moved into _WIN32 scope until other platforms gain support
|
void *fileData = NULL;
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
|
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
|
||||||
|
|
||||||
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
|
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
|
||||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize);
|
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, (int)dataSize);
|
||||||
|
|
||||||
#elif defined(__linux__) && defined(DRGFW_X11)
|
#elif defined(__linux__) && defined(DRGFW_X11)
|
||||||
|
|
||||||
|
|
@ -1070,7 +1082,7 @@ Image GetClipboardImage(void)
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
|
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
|
||||||
#endif // defined(_WIN32)
|
#endif // _WIN32
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||||
|
|
@ -1085,14 +1097,14 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
RGFW_window_showMouse(platform.window, false);
|
RGFW_window_showMouse(platform.window, false);
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
RGFW_window_captureRawMouse(platform.window, false);
|
RGFW_window_captureRawMouse(platform.window, false);
|
||||||
|
|
@ -1104,7 +1116,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorLocked = true;
|
CORE.Input.Mouse.cursorLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
RGFW_window_captureRawMouse(platform.window, true);
|
RGFW_window_captureRawMouse(platform.window, true);
|
||||||
|
|
@ -1115,9 +1127,37 @@ void DisableCursor(void)
|
||||||
|
|
||||||
// Swap back buffer with front buffer (screen drawing)
|
// Swap back buffer with front buffer (screen drawing)
|
||||||
void SwapScreenBuffer(void)
|
void SwapScreenBuffer(void)
|
||||||
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
if (platform.surface)
|
||||||
|
{
|
||||||
|
// copy rlsw pixel data to the surface framebuffer
|
||||||
|
swReadPixels(0, 0, platform.surfaceWidth, platform.surfaceHeight, SW_RGBA, SW_UNSIGNED_BYTE, platform.surfacePixels);
|
||||||
|
|
||||||
|
// Mac wants a different pixel order. I cant seem to get this to work any other way
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
unsigned char temp = 0;
|
||||||
|
unsigned char *p = NULL;
|
||||||
|
for (int i = 0; i < (platform.surfaceWidth * platform.surfaceHeight); i += 1)
|
||||||
|
{
|
||||||
|
p = platform.surfacePixels + (i * 4);
|
||||||
|
temp = p[0];
|
||||||
|
p[0] = p[2];
|
||||||
|
p[2] = temp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// blit surface to the window
|
||||||
|
RGFW_window_blitSurface(platform.window, platform.surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
{
|
{
|
||||||
RGFW_window_swapBuffers_OpenGL(platform.window);
|
RGFW_window_swapBuffers_OpenGL(platform.window);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition: Misc
|
// Module Functions Definition: Misc
|
||||||
|
|
@ -1126,7 +1166,9 @@ void SwapScreenBuffer(void)
|
||||||
// Get elapsed time measure in seconds since InitTimer()
|
// Get elapsed time measure in seconds since InitTimer()
|
||||||
double GetTime(void)
|
double GetTime(void)
|
||||||
{
|
{
|
||||||
double time = get_time_seconds() - CORE.Time.base;
|
// CORE.Time.base is nanoseconds as integer
|
||||||
|
double baseTime = (double)CORE.Time.base*1e-9;
|
||||||
|
double time = get_time_seconds() - baseTime;
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
@ -1308,6 +1350,9 @@ void PollInputEvents(void)
|
||||||
// Window events are also polled (Minimized, maximized, close...)
|
// Window events are also polled (Minimized, maximized, close...)
|
||||||
case RGFW_windowResized:
|
case RGFW_windowResized:
|
||||||
{
|
{
|
||||||
|
// set flag that the window was resized
|
||||||
|
CORE.Window.resizedLastFrame = true;
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||||
{
|
{
|
||||||
|
|
@ -1356,7 +1401,42 @@ void PollInputEvents(void)
|
||||||
CORE.Window.currentFbo.width = CORE.Window.screen.width;
|
CORE.Window.currentFbo.width = CORE.Window.screen.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.screen.height;
|
CORE.Window.currentFbo.height = CORE.Window.screen.height;
|
||||||
#endif
|
#endif
|
||||||
CORE.Window.resizedLastFrame = true;
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window);
|
||||||
|
CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f);
|
||||||
|
SetupViewport(platform.window->w * currentMonitor->pixelRatio, platform.window->h * currentMonitor->pixelRatio);
|
||||||
|
|
||||||
|
CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio;
|
||||||
|
CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio;
|
||||||
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
#endif
|
||||||
|
platform.surfaceWidth = CORE.Window.currentFbo.width;
|
||||||
|
platform.surfaceHeight = CORE.Window.currentFbo.height;
|
||||||
|
|
||||||
|
// in software mode we dont have the viewport so we need to reverse the highdpi changes
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||||
|
{
|
||||||
|
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||||
|
platform.surfaceWidth *= scaleDpi.x;
|
||||||
|
platform.surfaceHeight *= scaleDpi.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.surfacePixels != NULL)
|
||||||
|
{
|
||||||
|
RL_FREE(platform.surfacePixels);
|
||||||
|
platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.surface != NULL)
|
||||||
|
{
|
||||||
|
RGFW_surface_free(platform.surface);
|
||||||
|
platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8);
|
||||||
|
swResize(platform.surfaceWidth, platform.surfaceHeight);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} break;
|
} break;
|
||||||
case RGFW_windowMaximized:
|
case RGFW_windowMaximized:
|
||||||
{
|
{
|
||||||
|
|
@ -1447,37 +1527,35 @@ void PollInputEvents(void)
|
||||||
} break;
|
} break;
|
||||||
case RGFW_mousePosChanged:
|
case RGFW_mousePosChanged:
|
||||||
{
|
{
|
||||||
float event_x = 0.0f, event_y = 0.0f;
|
float mouseX = 0.0f;
|
||||||
|
float mouseY = 0.0f;
|
||||||
if (RGFW_window_isCaptured(platform.window))
|
if (RGFW_window_isCaptured(platform.window))
|
||||||
{
|
{
|
||||||
event_x = (float)rgfw_event.mouse.vecX;
|
mouseX = (float)rgfw_event.mouse.vecX;
|
||||||
event_y = (float)rgfw_event.mouse.vecY;
|
mouseY = (float)rgfw_event.mouse.vecY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
event_x = (float)rgfw_event.mouse.x;
|
mouseX = (float)rgfw_event.mouse.x;
|
||||||
event_y = (float)rgfw_event.mouse.y;
|
mouseY = (float)rgfw_event.mouse.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
{
|
|
||||||
double canvasWidth = 0.0;
|
double canvasWidth = 0.0;
|
||||||
double canvasHeight = 0.0;
|
double canvasHeight = 0.0;
|
||||||
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
|
||||||
event_x *= ((float)GetScreenWidth() / (float)canvasWidth);
|
mouseX *= ((float)GetScreenWidth()/(float)canvasWidth);
|
||||||
event_y *= ((float)GetScreenHeight() / (float)canvasHeight);
|
mouseY *= ((float)GetScreenHeight()/(float)canvasHeight);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (RGFW_window_isCaptured(platform.window))
|
if (RGFW_window_isCaptured(platform.window))
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentPosition.x += event_x;
|
CORE.Input.Mouse.currentPosition.x += mouseX;
|
||||||
CORE.Input.Mouse.currentPosition.y += event_y;
|
CORE.Input.Mouse.currentPosition.y += mouseY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentPosition.x = event_x;
|
CORE.Input.Mouse.currentPosition.x = mouseX;
|
||||||
CORE.Input.Mouse.currentPosition.y = event_y;
|
CORE.Input.Mouse.currentPosition.y = mouseY;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||||
|
|
@ -1599,10 +1677,62 @@ int InitPlatform(void)
|
||||||
// Initialize RGFW internal global state, only required systems
|
// Initialize RGFW internal global state, only required systems
|
||||||
unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND;
|
unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND;
|
||||||
|
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder);
|
||||||
|
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize);
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent);
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide);
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize);
|
||||||
|
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus);
|
||||||
|
|
||||||
|
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
|
||||||
|
{
|
||||||
|
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
// Check window creation flags
|
// Check window creation flags
|
||||||
|
|
||||||
|
// Init window in fullscreen mode if requested
|
||||||
|
// NOTE: Keeping original screen size for toggle
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
||||||
{
|
{
|
||||||
FLAG_SET(flags, RGFW_windowFullscreen);
|
FLAG_SET(flags, RGFW_windowFullscreen);
|
||||||
|
int result = RGFW_init();
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "RGFW: Failed to initialize RGFW");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Fullscreen applications default to the primary monitor
|
||||||
|
RGFW_monitor *monitor = RGFW_getPrimaryMonitor();
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "RGFW: Failed to get primary monitor");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default display resolution to that of the current mode
|
||||||
|
CORE.Window.display.width = monitor->mode.w;
|
||||||
|
CORE.Window.display.height = monitor->mode.h;
|
||||||
|
|
||||||
|
// Check if user requested some screen size
|
||||||
|
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
|
||||||
|
{
|
||||||
|
// Set some default screen size in case user decides to exit fullscreen mode
|
||||||
|
CORE.Window.previousScreen.width = 800;
|
||||||
|
CORE.Window.previousScreen.height = 450;
|
||||||
|
CORE.Window.previousPosition.x = (CORE.Window.display.width - CORE.Window.previousScreen.width)/2;
|
||||||
|
CORE.Window.previousPosition.y = (CORE.Window.display.height - CORE.Window.previousScreen.height)/2;
|
||||||
|
|
||||||
|
// Set screen width/height to the display width/height
|
||||||
|
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
|
||||||
|
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CORE.Window.previousScreen = CORE.Window.screen;
|
||||||
|
CORE.Window.screen = CORE.Window.display;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
|
||||||
|
|
@ -1610,16 +1740,16 @@ int InitPlatform(void)
|
||||||
FLAG_SET(flags, RGFW_windowedFullscreen);
|
FLAG_SET(flags, RGFW_windowedFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder);
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize);
|
{
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent);
|
#if !defined(__APPLE__)
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) FLAG_SET(flags, RGFW_windowFullscreen);
|
CORE.Window.screen.width = CORE.Window.screen.width * GetWindowScaleDPI().x;
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide);
|
CORE.Window.screen.height = CORE.Window.screen.height * GetWindowScaleDPI().y;
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize);
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Some OpenGL context attributes must be set before window creation
|
// NOTE: Some OpenGL context attributes must be set before window creation
|
||||||
// Check selection OpenGL version
|
// Check selection OpenGL version
|
||||||
|
|
||||||
RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL();
|
RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL();
|
||||||
if (rlGetVersion() == RL_OPENGL_21)
|
if (rlGetVersion() == RL_OPENGL_21)
|
||||||
{
|
{
|
||||||
|
|
@ -1636,22 +1766,16 @@ int InitPlatform(void)
|
||||||
hints->major = 4;
|
hints->major = 4;
|
||||||
hints->minor = 3;
|
hints->minor = 3;
|
||||||
}
|
}
|
||||||
|
else if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4;
|
|
||||||
|
|
||||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus);
|
|
||||||
|
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
|
||||||
{
|
{
|
||||||
#if !defined(__APPLE__)
|
hints->major = 1;
|
||||||
CORE.Window.screen.width = CORE.Window.screen.width * GetWindowScaleDPI().x;
|
hints->minor = 1;
|
||||||
CORE.Window.screen.height = CORE.Window.screen.height * GetWindowScaleDPI().y;
|
hints->renderer = RGFW_glSoftware;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4;
|
||||||
RGFW_setGlobalHints_OpenGL(hints);
|
RGFW_setGlobalHints_OpenGL(hints);
|
||||||
|
|
||||||
platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL);
|
platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL);
|
||||||
CORE.Time.base = get_time_seconds();
|
|
||||||
|
|
||||||
#ifndef PLATFORM_WEB_RGFW
|
#ifndef PLATFORM_WEB_RGFW
|
||||||
i32 screenSizeWidth;
|
i32 screenSizeWidth;
|
||||||
|
|
@ -1716,7 +1840,41 @@ int InitPlatform(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
// apple always scales for retina
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
RGFW_monitor* currentMonitor = RGFW_window_getMonitor(platform.window);
|
||||||
|
CORE.Window.screenScale = MatrixScale(currentMonitor->pixelRatio, currentMonitor->pixelRatio, 1.0f);
|
||||||
|
|
||||||
|
CORE.Window.render.width = CORE.Window.screen.width * currentMonitor->pixelRatio;
|
||||||
|
CORE.Window.render.height = CORE.Window.screen.height * currentMonitor->pixelRatio;
|
||||||
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
platform.surfaceWidth = CORE.Window.currentFbo.width;
|
||||||
|
platform.surfaceHeight = CORE.Window.currentFbo.height;
|
||||||
|
|
||||||
|
platform.surfacePixels = RL_MALLOC(platform.surfaceWidth * platform.surfaceHeight * 4);
|
||||||
|
if (platform.surfacePixels == NULL)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software pixel buffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform.surface = RGFW_window_createSurface(platform.window, platform.surfacePixels, platform.surfaceWidth, platform.surfaceHeight, RGFW_formatBGRA8);
|
||||||
|
|
||||||
|
if (platform.surface == NULL)
|
||||||
|
{
|
||||||
|
RL_FREE(platform.surfacePixels);
|
||||||
|
|
||||||
|
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize software surface");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
@ -1745,20 +1903,63 @@ int InitPlatform(void)
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(RGFW_WAYLAND)
|
#if defined(RGFW_WAYLAND)
|
||||||
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland, Software): Initialized successfully");
|
||||||
|
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software (fallback)): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully");
|
if (RGFW_usingWayland()) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully");
|
||||||
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully");
|
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully");
|
||||||
|
}
|
||||||
#elif defined(RGFW_X11)
|
#elif defined(RGFW_X11)
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully");
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software, (MacOS)): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, (MacOS)): Initialized successfully");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11, Software): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#elif defined (RGFW_WINDOWS)
|
#elif defined (RGFW_WINDOWS)
|
||||||
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32, Software): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully");
|
||||||
|
}
|
||||||
#elif defined(RGFW_WASM)
|
#elif defined(RGFW_WASM)
|
||||||
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs, Software): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully");
|
||||||
|
}
|
||||||
#elif defined(RGFW_MACOS)
|
#elif defined(RGFW_MACOS)
|
||||||
|
if (rlGetVersion() == RL_OPENGL_SOFTWARE)
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS, Software): Initialized successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully");
|
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mg_gamepads_init(&platform.minigamepad);
|
mg_gamepads_init(&platform.minigamepad);
|
||||||
|
|
@ -1771,6 +1972,18 @@ void ClosePlatform(void)
|
||||||
{
|
{
|
||||||
mg_gamepads_free(&platform.minigamepad);
|
mg_gamepads_free(&platform.minigamepad);
|
||||||
RGFW_window_close(platform.window);
|
RGFW_window_close(platform.window);
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
if (platform.surfacePixels != NULL)
|
||||||
|
{
|
||||||
|
RL_FREE(platform.surfacePixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.surface != NULL)
|
||||||
|
{
|
||||||
|
RGFW_surface_free(platform.surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keycode mapping
|
// Keycode mapping
|
||||||
|
|
@ -1788,33 +2001,35 @@ double get_time_seconds(void)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static LARGE_INTEGER freq = { 0 };
|
static LARGE_INTEGER freq = { 0 };
|
||||||
static int freq_init = 0;
|
static bool freqInitialized = false;
|
||||||
LARGE_INTEGER counter;
|
LARGE_INTEGER counter = { 0 };
|
||||||
if (!freq_init) {
|
if (!freqInitialized)
|
||||||
|
{
|
||||||
|
// Lazy initialization
|
||||||
QueryPerformanceFrequency(&freq);
|
QueryPerformanceFrequency(&freq);
|
||||||
freq_init = 1;
|
freqInitialized = true;
|
||||||
}
|
}
|
||||||
QueryPerformanceCounter(&counter);
|
QueryPerformanceCounter(&counter);
|
||||||
currentTime = (double)counter.QuadPart/(double)freq.QuadPart;
|
currentTime = (double)counter.QuadPart/(double)freq.QuadPart;
|
||||||
#elif defined(__EMSCRIPTEN__)
|
#elif defined(__EMSCRIPTEN__)
|
||||||
currentTime = emscripten_get_now()/1000.0;
|
currentTime = emscripten_get_now()/1000.0;
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
static mach_timebase_info_data_t tb;
|
static mach_timebase_info_data_t tb = { 0 };
|
||||||
static int tb_initialized = 0;
|
static bool tbInitialized = false;
|
||||||
|
if (!tbInitialized)
|
||||||
if (!tb_initialized) {
|
{
|
||||||
mach_timebase_info(&tb);
|
mach_timebase_info(&tb);
|
||||||
tb_initialized = 1;
|
tbInitialized = true;
|
||||||
}
|
}
|
||||||
uint64_t ticks = mach_absolute_time();
|
uint64_t ticks = mach_absolute_time();
|
||||||
|
|
||||||
currentTime = (double)ticks*(double)tb.numer/(double)tb.denom/1e9;
|
currentTime = (double)ticks*(double)tb.numer/(double)tb.denom/1e9;
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
struct timespec ts;
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
currentTime = (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
|
currentTime = (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
|
||||||
#else
|
#else
|
||||||
// fallback to cstd
|
// Fallback to cstd
|
||||||
currentTime = (double)clock()/(double)CLOCKS_PER_SEC;
|
currentTime = (double)clock()/(double)CLOCKS_PER_SEC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1144,7 +1144,7 @@ const char *GetClipboardText(void)
|
||||||
|
|
||||||
char *clipboard = SDL_GetClipboardText();
|
char *clipboard = SDL_GetClipboardText();
|
||||||
|
|
||||||
int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard);
|
int clipboardSize = snprintf(buffer, MAX_CLIPBOARD_BUFFER_LENGTH, "%s", clipboard);
|
||||||
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
|
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
|
||||||
{
|
{
|
||||||
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
|
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
|
||||||
|
|
@ -1227,7 +1227,7 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
#if defined(USING_VERSION_SDL3)
|
#if defined(USING_VERSION_SDL3)
|
||||||
|
|
@ -1238,7 +1238,7 @@ void HideCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
|
|
@ -1247,7 +1247,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorLocked = false;
|
CORE.Input.Mouse.cursorLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
|
@ -1528,6 +1528,10 @@ void PollInputEvents(void)
|
||||||
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED);
|
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
swResize(width, height);
|
||||||
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_ENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
|
case SDL_WINDOWEVENT_ENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
|
||||||
|
|
@ -1671,8 +1675,13 @@ void PollInputEvents(void)
|
||||||
} break;
|
} break;
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_MOUSEWHEEL:
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.currentWheelMove.x = (float)event.wheel.x;
|
#if defined(USING_VERSION_SDL3)
|
||||||
CORE.Input.Mouse.currentWheelMove.y = (float)event.wheel.y;
|
CORE.Input.Mouse.currentWheelMove.x = event.wheel.x;
|
||||||
|
CORE.Input.Mouse.currentWheelMove.y = event.wheel.y;
|
||||||
|
#else
|
||||||
|
CORE.Input.Mouse.currentWheelMove.x = event.wheel.preciseX;
|
||||||
|
CORE.Input.Mouse.currentWheelMove.y = event.wheel.preciseY;
|
||||||
|
#endif
|
||||||
} break;
|
} break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
{
|
{
|
||||||
|
|
@ -2064,7 +2073,8 @@ int InitPlatform(void)
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
|
||||||
|
|
@ -1063,14 +1063,14 @@ 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)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GetMonitorWidth not implemented");
|
//TRACELOG(LOG_WARNING, "GetMonitorWidth not implemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get selected monitor height (currently used by monitor)
|
// Get selected monitor height (currently used by monitor)
|
||||||
int GetMonitorHeight(int monitor)
|
int GetMonitorHeight(int monitor)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GetMonitorHeight not implemented");
|
//TRACELOG(LOG_WARNING, "GetMonitorHeight not implemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,7 +1105,7 @@ const char *GetMonitorName(int monitor)
|
||||||
// Get window position XY on monitor
|
// Get window position XY on monitor
|
||||||
Vector2 GetWindowPosition(void)
|
Vector2 GetWindowPosition(void)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "GetWindowPosition not implemented");
|
//TRACELOG(LOG_WARNING, "GetWindowPosition not implemented");
|
||||||
return (Vector2){ 0, 0 };
|
return (Vector2){ 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1146,7 +1146,7 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
// NOTE: Using SetCursor() instead of ShowCursor() because
|
// NOTE: Using SetCursor() instead of ShowCursor() because
|
||||||
|
|
@ -1155,7 +1155,7 @@ void HideCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
if (CORE.Input.Mouse.cursorLocked)
|
if (CORE.Input.Mouse.cursorLocked)
|
||||||
|
|
@ -1526,7 +1526,6 @@ int InitPlatform(void)
|
||||||
if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr);
|
if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HINSTANCE hInstance = GetModuleHandleW(0);
|
HINSTANCE hInstance = GetModuleHandleW(0);
|
||||||
|
|
||||||
// Define window class
|
// Define window class
|
||||||
|
|
@ -1643,7 +1642,8 @@ int InitPlatform(void)
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
@ -1760,13 +1760,31 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
||||||
memset(CORE.Input.Keyboard.previousKeyState, 0, sizeof(CORE.Input.Keyboard.previousKeyState));
|
memset(CORE.Input.Keyboard.previousKeyState, 0, sizeof(CORE.Input.Keyboard.previousKeyState));
|
||||||
memset(CORE.Input.Keyboard.currentKeyState, 0, sizeof(CORE.Input.Keyboard.currentKeyState));
|
memset(CORE.Input.Keyboard.currentKeyState, 0, sizeof(CORE.Input.Keyboard.currentKeyState));
|
||||||
} break;
|
} break;
|
||||||
case WM_SIZING:
|
case WM_SIZING: // Sent to a window that the user is resizing
|
||||||
{
|
{
|
||||||
if (!(CORE.Window.flags & FLAG_WINDOW_RESIZABLE))
|
if (CORE.Window.flags & FLAG_WINDOW_RESIZABLE)
|
||||||
TRACELOG(LOG_WARNING, "WIN32: WINDOW: Trying to resize a non-resizable window");
|
{
|
||||||
|
//HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
||||||
|
}
|
||||||
|
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
} break;
|
} break;
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
// WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc()
|
||||||
|
// in response to WM_WINDOWPOSCHANGED but looks like when a window is created,
|
||||||
|
// this message can be obtained without getting WM_WINDOWPOSCHANGED
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
// WARNING: Waiting two frames before resizing because software-renderer backend is initilized with swInit() later
|
||||||
|
// than InitPlatform(), that triggers WM_SIZE, so avoid crashing
|
||||||
|
if (CORE.Time.frameCounter > 2) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
||||||
|
#else
|
||||||
|
// NOTE: This message is only triggered on window creation
|
||||||
|
HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
||||||
|
#endif
|
||||||
|
result = 0; // If an application processes WM_SIZE message, it should return zero
|
||||||
|
} break;
|
||||||
case WM_GETMINMAXINFO:
|
case WM_GETMINMAXINFO:
|
||||||
{
|
{
|
||||||
DWORD style = MakeWindowStyle(platform.desiredFlags);
|
DWORD style = MakeWindowStyle(platform.desiredFlags);
|
||||||
|
|
@ -1865,19 +1883,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case WM_SIZE:
|
//case WM_MOVE: break;
|
||||||
{
|
|
||||||
// WARNING: Don't trust the docs, they say this message can not be obtained if not calling DefWindowProc()
|
|
||||||
// in response to WM_WINDOWPOSCHANGED but looks like when a window is created,
|
|
||||||
// this message can be obtained without getting WM_WINDOWPOSCHANGED
|
|
||||||
// WARNING: This call fails for Software-Renderer backend
|
|
||||||
//HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
|
||||||
} break;
|
|
||||||
//case WM_MOVE
|
|
||||||
case WM_WINDOWPOSCHANGED:
|
case WM_WINDOWPOSCHANGED:
|
||||||
{
|
{
|
||||||
WINDOWPOS *pos = (WINDOWPOS*)lparam;
|
WINDOWPOS *pos = (WINDOWPOS*)lparam;
|
||||||
if (!(pos->flags & SWP_NOSIZE)) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
if (!(pos->flags & SWP_NOSIZE)) HandleWindowResize(hwnd, &platform.appScreenWidth, &platform.appScreenHeight);
|
||||||
|
|
||||||
|
DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
} break;
|
} break;
|
||||||
case WM_GETDPISCALEDSIZE:
|
case WM_GETDPISCALEDSIZE:
|
||||||
{
|
{
|
||||||
|
|
@ -2091,6 +2103,10 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height)
|
||||||
|
|
||||||
CORE.Window.screenScale = MatrixScale( (float)CORE.Window.render.width/CORE.Window.screen.width,
|
CORE.Window.screenScale = MatrixScale( (float)CORE.Window.render.width/CORE.Window.screen.width,
|
||||||
(float)CORE.Window.render.height/CORE.Window.screen.height, 1.0f);
|
(float)CORE.Window.render.height/CORE.Window.screen.height, 1.0f);
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
|
swResize(clientSize.cx, clientSize.cy);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update window style
|
// Update window style
|
||||||
|
|
|
||||||
|
|
@ -266,9 +266,12 @@ static void PollKeyboardEvents(void); // Process evdev keyboard events
|
||||||
static void PollGamepadEvents(void); // Process evdev gamepad events
|
static void PollGamepadEvents(void); // Process evdev gamepad events
|
||||||
static void PollMouseEvents(void); // Process evdev mouse events
|
static void PollMouseEvents(void); // Process evdev mouse events
|
||||||
|
|
||||||
|
// Not used by software rendering.
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
|
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
|
||||||
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
|
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
|
||||||
static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list
|
static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list
|
||||||
|
#endif
|
||||||
|
|
||||||
static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform())
|
static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform())
|
||||||
|
|
||||||
|
|
@ -561,13 +564,13 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -577,7 +580,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorLocked = false;
|
CORE.Input.Mouse.cursorLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -837,14 +840,8 @@ void SwapScreenBuffer(void)
|
||||||
uint32_t height = mode->vdisplay;
|
uint32_t height = mode->vdisplay;
|
||||||
|
|
||||||
// Dumb buffers use a fixed format based on bpp
|
// Dumb buffers use a fixed format based on bpp
|
||||||
#if SW_COLOR_BUFFER_BITS == 24
|
|
||||||
const uint32_t bpp = 32; // 32 bits per pixel (XRGB8888 format)
|
const uint32_t bpp = 32; // 32 bits per pixel (XRGB8888 format)
|
||||||
const uint32_t depth = 24; // Color depth, here only 24 bits, alpha is not used
|
const uint32_t depth = 24; // Color depth, here only 24 bits, alpha is not used
|
||||||
#else
|
|
||||||
// REVIEW: Not sure how it will be interpreted (RGB or RGBA?)
|
|
||||||
const uint32_t bpp = SW_COLOR_BUFFER_BITS;
|
|
||||||
const uint32_t depth = SW_COLOR_BUFFER_BITS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create a dumb buffer for software rendering
|
// Create a dumb buffer for software rendering
|
||||||
struct drm_mode_create_dumb creq = { 0 };
|
struct drm_mode_create_dumb creq = { 0 };
|
||||||
|
|
@ -899,7 +896,7 @@ void SwapScreenBuffer(void)
|
||||||
|
|
||||||
// Copy the software rendered buffer to the dumb buffer with scaling if needed
|
// Copy the software rendered buffer to the dumb buffer with scaling if needed
|
||||||
// NOTE: RLSW will make a simple copy if the dimensions match
|
// NOTE: RLSW will make a simple copy if the dimensions match
|
||||||
swBlitFramebuffer(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
|
swBlitPixels(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
|
||||||
|
|
||||||
// Unmap the buffer
|
// Unmap the buffer
|
||||||
munmap(dumbBuffer, creq.size);
|
munmap(dumbBuffer, creq.size);
|
||||||
|
|
@ -1009,7 +1006,7 @@ double GetTime(void)
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
struct timespec ts = { 0 };
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||||
|
|
||||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||||
|
|
||||||
|
|
@ -1432,7 +1429,7 @@ int InitPlatform(void)
|
||||||
if (eglGetPlatformDisplayEXT != NULL) platform.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, platform.gbmDevice, NULL);
|
if (eglGetPlatformDisplayEXT != NULL) platform.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, platform.gbmDevice, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case extension not found or display could not be retrieved, try useing legacy version
|
// In case extension not found or display could not be retrieved, try using legacy version
|
||||||
if (platform.device == EGL_NO_DISPLAY) platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice);
|
if (platform.device == EGL_NO_DISPLAY) platform.device = eglGetDisplay((EGLNativeDisplayType)platform.gbmDevice);
|
||||||
#endif
|
#endif
|
||||||
if (platform.device == EGL_NO_DISPLAY)
|
if (platform.device == EGL_NO_DISPLAY)
|
||||||
|
|
@ -1555,12 +1552,6 @@ int InitPlatform(void)
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1586,13 +1577,14 @@ int InitPlatform(void)
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
#endif
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully (Software Rendering)");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) MinimizeWindow();
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) MinimizeWindow();
|
||||||
|
|
||||||
|
|
@ -2571,6 +2563,7 @@ static void PollMouseEvents(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
// Search matching DRM mode in connector's mode list
|
// Search matching DRM mode in connector's mode list
|
||||||
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)
|
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)
|
||||||
{
|
{
|
||||||
|
|
@ -2659,6 +2652,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
||||||
|
|
||||||
return nearestIndex;
|
return nearestIndex;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Compute framebuffer size relative to screen size and display size
|
// Compute framebuffer size relative to screen size and display size
|
||||||
// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified
|
// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified
|
||||||
|
|
|
||||||
|
|
@ -324,13 +324,13 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -339,7 +339,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -364,13 +364,15 @@ double GetTime(void)
|
||||||
{
|
{
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
LARGE_INTEGER now = { 0 };
|
LARGE_INTEGER currentTicks = { 0 };
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(¤tTicks);
|
||||||
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
|
||||||
|
time = (double)(currentTicks.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||||
struct timespec ts = { 0 };
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||||
|
|
||||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||||
#endif
|
#endif
|
||||||
return time;
|
return time;
|
||||||
|
|
|
||||||
|
|
@ -303,13 +303,13 @@ void ShowCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
CORE.Input.Mouse.cursorHidden = true;
|
CORE.Input.Mouse.cursorHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -318,7 +318,7 @@ void EnableCursor(void)
|
||||||
CORE.Input.Mouse.cursorHidden = false;
|
CORE.Input.Mouse.cursorHidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
// Set cursor position in the middle
|
// Set cursor position in the middle
|
||||||
|
|
@ -341,9 +341,11 @@ void SwapScreenBuffer(void)
|
||||||
double GetTime(void)
|
double GetTime(void)
|
||||||
{
|
{
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
|
|
||||||
struct timespec ts = { 0 };
|
struct timespec ts = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||||
|
|
||||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
|
|
@ -474,12 +476,6 @@ int InitPlatform(void)
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
|
||||||
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -494,7 +490,8 @@ int InitPlatform(void)
|
||||||
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
||||||
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ typedef struct {
|
||||||
|
|
||||||
char canvasId[64]; // Keep current canvas id where wasm app is running
|
char canvasId[64]; // Keep current canvas id where wasm app is running
|
||||||
// NOTE: Useful when trying to run multiple wasms in different canvases in same webpage
|
// NOTE: Useful when trying to run multiple wasms in different canvases in same webpage
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
#if defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||||
unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format)
|
unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -913,7 +912,7 @@ void ShowCursor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
if (!CORE.Input.Mouse.cursorHidden)
|
if (!CORE.Input.Mouse.cursorHidden)
|
||||||
|
|
@ -924,7 +923,7 @@ void HideCursor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
emscripten_exit_pointerlock();
|
emscripten_exit_pointerlock();
|
||||||
|
|
@ -935,7 +934,7 @@ void EnableCursor(void)
|
||||||
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
|
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
emscripten_request_pointerlock(platform.canvasId, 1);
|
emscripten_request_pointerlock(platform.canvasId, 1);
|
||||||
|
|
@ -1423,7 +1422,8 @@ int InitPlatform(void)
|
||||||
CORE.Window.currentFbo.width = fbWidth;
|
CORE.Window.currentFbo.width = fbWidth;
|
||||||
CORE.Window.currentFbo.height = fbHeight;
|
CORE.Window.currentFbo.height = fbHeight;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
|
||||||
|
|
@ -891,7 +891,7 @@ void ShowCursor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hides mouse cursor
|
// Hide mouse cursor
|
||||||
void HideCursor(void)
|
void HideCursor(void)
|
||||||
{
|
{
|
||||||
if (!CORE.Input.Mouse.cursorHidden)
|
if (!CORE.Input.Mouse.cursorHidden)
|
||||||
|
|
@ -902,7 +902,7 @@ void HideCursor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enables cursor (unlock cursor)
|
// Enable cursor (unlock cursor)
|
||||||
void EnableCursor(void)
|
void EnableCursor(void)
|
||||||
{
|
{
|
||||||
emscripten_exit_pointerlock();
|
emscripten_exit_pointerlock();
|
||||||
|
|
@ -913,7 +913,7 @@ void EnableCursor(void)
|
||||||
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
|
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables cursor (lock cursor)
|
// Disable cursor (lock cursor)
|
||||||
void DisableCursor(void)
|
void DisableCursor(void)
|
||||||
{
|
{
|
||||||
emscripten_request_pointerlock(platform.canvasId, 1);
|
emscripten_request_pointerlock(platform.canvasId, 1);
|
||||||
|
|
@ -1245,7 +1245,8 @@ int InitPlatform(void)
|
||||||
CORE.Window.currentFbo.width = fbWidth;
|
CORE.Window.currentFbo.width = fbWidth;
|
||||||
CORE.Window.currentFbo.height = fbHeight;
|
CORE.Window.currentFbo.height = fbHeight;
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully %s",
|
||||||
|
FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)? "(HighDPI)" : "");
|
||||||
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||||
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
||||||
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
|
||||||
|
|
|
||||||
116
src/raudio.c
116
src/raudio.c
|
|
@ -11,22 +11,22 @@
|
||||||
* - Play/Stop/Pause/Resume loaded audio
|
* - Play/Stop/Pause/Resume loaded audio
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_MODULE_RAUDIO
|
* #define SUPPORT_MODULE_RAUDIO 1
|
||||||
* raudio module is included in the build
|
* raudio module is included in the build
|
||||||
*
|
*
|
||||||
* #define RAUDIO_STANDALONE
|
* #define RAUDIO_STANDALONE
|
||||||
* Define to use the module as standalone library (independently of raylib)
|
* Define to use the module as standalone library (independently of raylib)
|
||||||
* Required types and functions are defined in the same module
|
* Required types and functions are defined in the same module
|
||||||
*
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_WAV
|
* #define SUPPORT_FILEFORMAT_WAV 1
|
||||||
* #define SUPPORT_FILEFORMAT_OGG
|
* #define SUPPORT_FILEFORMAT_OGG 1
|
||||||
* #define SUPPORT_FILEFORMAT_MP3
|
* #define SUPPORT_FILEFORMAT_MP3 1
|
||||||
* #define SUPPORT_FILEFORMAT_QOA
|
* #define SUPPORT_FILEFORMAT_QOA 1
|
||||||
* #define SUPPORT_FILEFORMAT_FLAC
|
* #define SUPPORT_FILEFORMAT_FLAC 0
|
||||||
* #define SUPPORT_FILEFORMAT_XM
|
* #define SUPPORT_FILEFORMAT_XM 1
|
||||||
* #define SUPPORT_FILEFORMAT_MOD
|
* #define SUPPORT_FILEFORMAT_MOD 1
|
||||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||||
* supported by default, to remove support, comment unrequired #define in this module
|
* supported by default, to remove support, #define as 0 in this module or your build system
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio)
|
* miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio)
|
||||||
|
|
@ -378,7 +378,7 @@ struct rAudioProcessor {
|
||||||
rAudioProcessor *prev; // Previous audio processor on the list
|
rAudioProcessor *prev; // Previous audio processor on the list
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision
|
#define AudioBuffer rAudioBuffer // WARNING: Renamed to avoid symbol collision with CoreAudio (macOS) AudioBuffer type
|
||||||
|
|
||||||
// Audio data context
|
// Audio data context
|
||||||
typedef struct AudioData {
|
typedef struct AudioData {
|
||||||
|
|
@ -434,6 +434,7 @@ static const char *GetFileName(const char *filePath); // Get point
|
||||||
static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
|
static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
|
||||||
|
|
||||||
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
|
static void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
|
||||||
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -857,7 +858,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||||
{
|
{
|
||||||
drmp3_config config = { 0 };
|
drmp3_config config = { 0 };
|
||||||
unsigned long long int totalFrameCount = 0;
|
unsigned long long totalFrameCount = 0;
|
||||||
|
|
||||||
// NOTE: Forcing conversion to 32bit float sample size on reading
|
// NOTE: Forcing conversion to 32bit float sample size on reading
|
||||||
wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
|
wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
|
||||||
|
|
@ -867,7 +868,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
{
|
{
|
||||||
wave.channels = config.channels;
|
wave.channels = config.channels;
|
||||||
wave.sampleRate = config.sampleRate;
|
wave.sampleRate = config.sampleRate;
|
||||||
wave.frameCount = (int)totalFrameCount;
|
wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
||||||
|
|
||||||
|
|
@ -895,13 +896,13 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
#if SUPPORT_FILEFORMAT_FLAC
|
#if SUPPORT_FILEFORMAT_FLAC
|
||||||
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
||||||
{
|
{
|
||||||
unsigned long long int totalFrameCount = 0;
|
unsigned long long totalFrameCount = 0;
|
||||||
|
|
||||||
// NOTE: Forcing conversion to 16bit sample size on reading
|
// NOTE: Forcing conversion to 16bit sample size on reading
|
||||||
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
||||||
wave.sampleSize = 16;
|
wave.sampleSize = 16;
|
||||||
|
|
||||||
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
|
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -912,7 +913,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
return wave;
|
return wave;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if wave data is valid (data loaded and parameters)
|
// Check if wave data is valid (data loaded and parameters)
|
||||||
bool IsWaveValid(Wave wave)
|
bool IsWaveValid(Wave wave)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
@ -963,12 +964,8 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
||||||
|
|
||||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
|
||||||
return sound; // early return to avoid dereferencing the audioBuffer null pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
||||||
|
|
||||||
|
|
@ -978,11 +975,13 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
sound.stream.buffer = audioBuffer;
|
sound.stream.buffer = audioBuffer;
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||||
|
}
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone sound from existing sound data, clone does not own wave data
|
// Load sound alias, clone sound from existing sound data, clone does not own wave data
|
||||||
// NOTE: Wave data must be unallocated manually and will be shared across all clones
|
// NOTE: Wave data must be unallocated manually and will be shared across all clones
|
||||||
Sound LoadSoundAlias(Sound source)
|
Sound LoadSoundAlias(Sound source)
|
||||||
{
|
{
|
||||||
|
|
@ -992,12 +991,8 @@ Sound LoadSoundAlias(Sound source)
|
||||||
{
|
{
|
||||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
|
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer != NULL)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
|
||||||
return sound; // Early return to avoid dereferencing the audioBuffer null pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
||||||
audioBuffer->data = source.stream.buffer->data;
|
audioBuffer->data = source.stream.buffer->data;
|
||||||
|
|
||||||
|
|
@ -1012,11 +1007,13 @@ Sound LoadSoundAlias(Sound source)
|
||||||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
sound.stream.buffer = audioBuffer;
|
sound.stream.buffer = audioBuffer;
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||||
|
}
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if a sound is valid (data loaded and buffers initialized)
|
// Check if a sound is valid (data loaded and buffers initialized)
|
||||||
bool IsSoundValid(Sound sound)
|
bool IsSoundValid(Sound sound)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
@ -1051,6 +1048,7 @@ void UnloadSoundAlias(Sound alias)
|
||||||
{
|
{
|
||||||
UntrackAudioBuffer(alias.stream.buffer);
|
UntrackAudioBuffer(alias.stream.buffer);
|
||||||
ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
|
ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
|
||||||
|
RL_FREE(alias.stream.buffer->converterResidual);
|
||||||
RL_FREE(alias.stream.buffer);
|
RL_FREE(alias.stream.buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1071,7 +1069,7 @@ void UpdateSound(Sound sound, const void *data, int frameCount)
|
||||||
// Export wave data to file
|
// Export wave data to file
|
||||||
bool ExportWave(Wave wave, const char *fileName)
|
bool ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (false) { }
|
if (false) { }
|
||||||
#if SUPPORT_FILEFORMAT_WAV
|
#if SUPPORT_FILEFORMAT_WAV
|
||||||
|
|
@ -1088,11 +1086,11 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
|
|
||||||
void *fileData = NULL;
|
void *fileData = NULL;
|
||||||
size_t fileDataSize = 0;
|
size_t fileDataSize = 0;
|
||||||
success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
result = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
||||||
if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
if (result) result = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
||||||
drwav_result result = drwav_uninit(&wav);
|
drwav_result result = drwav_uninit(&wav);
|
||||||
|
|
||||||
if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
if (result == DRWAV_SUCCESS) result = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
||||||
|
|
||||||
drwav_free(fileData, NULL);
|
drwav_free(fileData, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -1108,7 +1106,7 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
qoa.samples = wave.frameCount;
|
qoa.samples = wave.frameCount;
|
||||||
|
|
||||||
int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa);
|
int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa);
|
||||||
if (bytesWritten > 0) success = true;
|
if (bytesWritten > 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
|
else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
|
||||||
}
|
}
|
||||||
|
|
@ -1117,19 +1115,19 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
// Export raw sample data (without header)
|
// Export raw sample data (without header)
|
||||||
// NOTE: It's up to the user to track wave parameters
|
// NOTE: It's up to the user to track wave parameters
|
||||||
success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
result = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
if (result) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export wave sample data to code (.h)
|
// Export wave sample data to code (.h)
|
||||||
bool ExportWaveAsCode(Wave wave, const char *fileName)
|
bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -1183,14 +1181,14 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play a sound
|
// Play a sound
|
||||||
|
|
@ -1706,8 +1704,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
|
|
||||||
// Copy data to allocated memory for default UnloadMusicStream
|
// Copy data to allocated memory for default UnloadMusicStream
|
||||||
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
|
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
|
||||||
int it = dataSize/sizeof(unsigned char);
|
for (int i = 0; i < dataSize; i++) newData[i] = data[i];
|
||||||
for (int i = 0; i < it; i++) newData[i] = data[i];
|
|
||||||
|
|
||||||
// Memory loaded version for jar_mod_load_file()
|
// Memory loaded version for jar_mod_load_file()
|
||||||
if (dataSize && (dataSize < 32*1024*1024))
|
if (dataSize && (dataSize < 32*1024*1024))
|
||||||
|
|
@ -1754,7 +1751,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if a music stream is valid (context and buffers initialized)
|
// Check if a music stream is valid (context and buffers initialized)
|
||||||
bool IsMusicValid(Music music)
|
bool IsMusicValid(Music music)
|
||||||
{
|
{
|
||||||
return ((music.ctxData != NULL) && // Validate context loaded
|
return ((music.ctxData != NULL) && // Validate context loaded
|
||||||
|
|
@ -1767,6 +1764,8 @@ bool IsMusicValid(Music music)
|
||||||
// Unload music stream
|
// Unload music stream
|
||||||
void UnloadMusicStream(Music music)
|
void UnloadMusicStream(Music music)
|
||||||
{
|
{
|
||||||
|
if (IsMusicStreamPlaying(music)) StopMusicStream(music);
|
||||||
|
|
||||||
UnloadAudioStream(music.stream);
|
UnloadAudioStream(music.stream);
|
||||||
|
|
||||||
if (music.ctxData != NULL)
|
if (music.ctxData != NULL)
|
||||||
|
|
@ -2069,7 +2068,7 @@ void SetMusicPitch(Music music, float pitch)
|
||||||
SetAudioBufferPitch(music.stream.buffer, pitch);
|
SetAudioBufferPitch(music.stream.buffer, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set pan for a music
|
// Set pan for music
|
||||||
void SetMusicPan(Music music, float pan)
|
void SetMusicPan(Music music, float pan)
|
||||||
{
|
{
|
||||||
SetAudioBufferPan(music.stream.buffer, pan);
|
SetAudioBufferPan(music.stream.buffer, pan);
|
||||||
|
|
@ -2157,7 +2156,7 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if an audio stream is valid (buffers initialized)
|
// Check if an audio stream is valid (buffers initialized)
|
||||||
bool IsAudioStreamValid(AudioStream stream)
|
bool IsAudioStreamValid(AudioStream stream)
|
||||||
{
|
{
|
||||||
return ((stream.buffer != NULL) && // Validate stream buffer
|
return ((stream.buffer != NULL) && // Validate stream buffer
|
||||||
|
|
@ -2187,12 +2186,15 @@ void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
|
||||||
// Check if any audio stream buffers requires refill
|
// Check if any audio stream buffers requires refill
|
||||||
bool IsAudioStreamProcessed(AudioStream stream)
|
bool IsAudioStreamProcessed(AudioStream stream)
|
||||||
{
|
{
|
||||||
if (stream.buffer == NULL) return false;
|
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
if (stream.buffer != NULL)
|
||||||
|
{
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
|
result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2882,9 +2884,17 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unload file data allocated by LoadFileData()
|
||||||
|
static void UnloadFileData(unsigned char *data)
|
||||||
|
{
|
||||||
|
RL_FREE(data);
|
||||||
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
{
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(fileName, "wb");
|
FILE *file = fopen(fileName, "wb");
|
||||||
|
|
@ -2902,21 +2912,23 @@ static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save text data to file (write), string must be '\0' terminated
|
// Save text data to file (write), string must be '\0' terminated
|
||||||
static bool SaveFileText(const char *fileName, char *text)
|
static bool SaveFileText(const char *fileName, char *text)
|
||||||
{
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(fileName, "wt");
|
FILE *file = fopen(fileName, "wt");
|
||||||
|
|
@ -2934,16 +2946,16 @@ static bool SaveFileText(const char *fileName, char *text)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
GLFW_ICON ICON "raylib.ico"
|
GLFW_ICON ICON "raylib.ico"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 5,5,0,0
|
FILEVERSION 6,0,0,0
|
||||||
PRODUCTVERSION 5,5,0,0
|
PRODUCTVERSION 6,0,0,0
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
@ -11,12 +11,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "raylib technologies"
|
VALUE "CompanyName", "raylib technologies"
|
||||||
VALUE "FileDescription", "raylib dynamic library (www.raylib.com)"
|
VALUE "FileDescription", "raylib dynamic library (www.raylib.com)"
|
||||||
VALUE "FileVersion", "5.5.0"
|
VALUE "FileVersion", "6.0.0"
|
||||||
VALUE "InternalName", "raylib.dll"
|
VALUE "InternalName", "raylib.dll"
|
||||||
VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)"
|
VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)"
|
||||||
VALUE "OriginalFilename", "raylib.dll"
|
VALUE "OriginalFilename", "raylib.dll"
|
||||||
VALUE "ProductName", "raylib"
|
VALUE "ProductName", "raylib"
|
||||||
VALUE "ProductVersion", "5.5.0"
|
VALUE "ProductVersion", "6.0.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
Binary file not shown.
147
src/raylib.h
147
src/raylib.h
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib v6.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
* raylib v6.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||||
*
|
*
|
||||||
* FEATURES:
|
* FEATURES:
|
||||||
* - NO external dependencies, all required libraries included with raylib
|
* - NO external dependencies, all required libraries included with raylib
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
* - Software renderer optional, for systems with no GPU: [rlsw]
|
* - Software renderer optional, for systems with no GPU: [rlsw]
|
||||||
* - Custom OpenGL abstraction layer (usable as standalone module): [rlgl]
|
* - Custom OpenGL abstraction layer (usable as standalone module): [rlgl]
|
||||||
* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
|
* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
|
||||||
* - Many texture formats supportted, including compressed formats (DXT, ETC, ASTC)
|
* - Many texture formats supported, including compressed formats (DXT, ETC, ASTC)
|
||||||
* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
|
* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
|
||||||
* - Flexible Materials system, supporting classic maps and PBR maps
|
* - Flexible Materials system, supporting classic maps and PBR maps
|
||||||
* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF)
|
* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF)
|
||||||
|
|
@ -35,14 +35,14 @@
|
||||||
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
|
* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
|
||||||
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
|
* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
|
||||||
* [rcore] rprand (Ramon Santamaria) for pseudo-random numbers generation
|
* [rcore] rprand (Ramon Santamaria) for pseudo-random numbers generation
|
||||||
* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage
|
* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image management
|
||||||
* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...)
|
* [rtextures] stb_image (Sean Barrett) for images loading (BMP, TGA, PNG, JPEG, HDR...)
|
||||||
* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
|
* [rtextures] stb_image_write (Sean Barrett) for image writing (BMP, TGA, PNG, JPG)
|
||||||
* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms
|
* [rtextures] stb_image_resize2 (Sean Barrett) for image resizing algorithms
|
||||||
* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation
|
* [rtextures] stb_perlin (Sean Barrett) for Perlin Noise image generation
|
||||||
* [rtextures] rltexgpu (Ramon Santamaria) for GPU-compressed texture formats
|
* [rtextures] rltexgpu (Ramon Santamaria) for GPU-compressed texture formats
|
||||||
* [rtext] stb_truetype (Sean Barret) for ttf fonts loading
|
* [rtext] stb_truetype (Sean Barrett) for ttf fonts loading
|
||||||
* [rtext] stb_rect_pack (Sean Barret) for rectangles packing
|
* [rtext] stb_rect_pack (Sean Barrett) for rectangles packing
|
||||||
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
|
* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
|
||||||
* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
|
* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
|
||||||
* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
|
* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
|
||||||
|
|
@ -51,10 +51,10 @@
|
||||||
* [raudio] dr_wav (David Reid) for WAV audio file loading
|
* [raudio] dr_wav (David Reid) for WAV audio file loading
|
||||||
* [raudio] dr_flac (David Reid) for FLAC audio file loading
|
* [raudio] dr_flac (David Reid) for FLAC audio file loading
|
||||||
* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
|
* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
|
||||||
* [raudio] stb_vorbis (Sean Barret) for OGG audio loading
|
* [raudio] stb_vorbis (Sean Barrett) for OGG audio loading
|
||||||
* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading
|
* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading
|
||||||
* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading
|
* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading
|
||||||
* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage
|
* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio management
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
|
|
@ -87,9 +87,9 @@
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION_MAJOR 6
|
#define RAYLIB_VERSION_MAJOR 6
|
||||||
#define RAYLIB_VERSION_MINOR 0
|
#define RAYLIB_VERSION_MINOR 1
|
||||||
#define RAYLIB_VERSION_PATCH 0
|
#define RAYLIB_VERSION_PATCH 0
|
||||||
#define RAYLIB_VERSION "6.0"
|
#define RAYLIB_VERSION "6.1-dev"
|
||||||
|
|
||||||
// Function specifiers in case library is build/used as a shared library
|
// Function specifiers in case library is build/used as a shared library
|
||||||
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
|
||||||
|
|
@ -203,12 +203,14 @@
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Boolean type
|
// Boolean type
|
||||||
|
#if !defined(__cplusplus)
|
||||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#elif !defined(__cplusplus) && !defined(bool)
|
#elif !defined(bool)
|
||||||
typedef enum bool { false = 0, true = !false } bool;
|
typedef enum bool { false = 0, true = !false } bool;
|
||||||
#define RL_BOOL_TYPE
|
#define RL_BOOL_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Vector2, 2 components
|
// Vector2, 2 components
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
|
|
@ -965,7 +967,7 @@ typedef enum {
|
||||||
// WARNING: These callbacks are intended for advanced users
|
// WARNING: These callbacks are intended for advanced users
|
||||||
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
|
||||||
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, const 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, const char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
|
@ -1034,23 +1036,23 @@ RLAPI void EnableEventWaiting(void); // Enable wait
|
||||||
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
|
||||||
|
|
||||||
// Cursor-related functions
|
// Cursor-related functions
|
||||||
RLAPI void ShowCursor(void); // Shows cursor
|
RLAPI void ShowCursor(void); // Show cursor
|
||||||
RLAPI void HideCursor(void); // Hides cursor
|
RLAPI void HideCursor(void); // Hide cursor
|
||||||
RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
|
RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
|
||||||
RLAPI void EnableCursor(void); // Enables cursor (unlock cursor)
|
RLAPI void EnableCursor(void); // Enable cursor (unlock cursor)
|
||||||
RLAPI void DisableCursor(void); // Disables cursor (lock cursor)
|
RLAPI void DisableCursor(void); // Disable cursor (lock cursor)
|
||||||
RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen
|
RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen
|
||||||
|
|
||||||
// Drawing-related functions
|
// Drawing-related functions
|
||||||
RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color)
|
RLAPI void ClearBackground(Color color); // Clear background (framebuffer) to color
|
||||||
RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing
|
RLAPI void BeginDrawing(void); // Begin canvas (framebuffer) drawing
|
||||||
RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering)
|
RLAPI void EndDrawing(void); // End canvas (framebuffer) drawing and swap buffers (double buffering)
|
||||||
RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D)
|
RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D)
|
||||||
RLAPI void EndMode2D(void); // Ends 2D mode with custom camera
|
RLAPI void EndMode2D(void); // End 2D mode with custom camera
|
||||||
RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D)
|
RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D)
|
||||||
RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
|
RLAPI void EndMode3D(void); // End 3D mode and returns to default 2D orthographic mode
|
||||||
RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture
|
RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture
|
||||||
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
RLAPI void EndTextureMode(void); // End drawing to render texture
|
||||||
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||||
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
|
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||||
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
|
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
|
||||||
|
|
@ -1081,10 +1083,10 @@ RLAPI void UnloadShader(Shader shader); // Un
|
||||||
#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions
|
#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions
|
||||||
RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse)
|
RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse)
|
||||||
RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport
|
RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport
|
||||||
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position
|
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get screen space position for a 3d world space position
|
||||||
RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position
|
RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get sized screen space position for a 3d world space position
|
||||||
RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position
|
RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get screen space position for a 2d camera world space position
|
||||||
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position
|
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get world space position for a 2d camera screen space position
|
||||||
RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
|
RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
|
||||||
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
|
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
|
||||||
|
|
||||||
|
|
@ -1126,7 +1128,7 @@ RLAPI void MemFree(void *ptr); // Internal memo
|
||||||
// File system management functions
|
// File system management functions
|
||||||
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
|
||||||
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
|
||||||
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
|
RLAPI bool SaveFileData(const char *fileName, const void *data, int dataSize); // Save data to file from byte array (write), 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 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()
|
||||||
|
|
@ -1161,8 +1163,8 @@ RLAPI int MakeDirectory(const char *dirPath); // Create di
|
||||||
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
||||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||||
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
||||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
|
||||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`
|
||||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||||
|
|
@ -1175,10 +1177,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
|
||||||
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
|
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
|
||||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), 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 char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), 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(const 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(const 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(const unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||||
RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes)
|
RLAPI unsigned int *ComputeSHA256(const unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes)
|
||||||
|
|
||||||
// Automation events functionality
|
// Automation events functionality
|
||||||
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||||
|
|
@ -1245,7 +1247,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
||||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture has been detected
|
||||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
|
@ -1279,10 +1281,10 @@ RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color);
|
||||||
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
|
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
|
||||||
RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
|
RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
|
||||||
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
|
RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle
|
||||||
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
|
||||||
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
|
||||||
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
|
|
||||||
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
|
||||||
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
|
||||||
|
|
@ -1302,12 +1304,13 @@ RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color c
|
||||||
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
|
||||||
RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges
|
RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges
|
||||||
RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline
|
RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle lines with rounded edges outline
|
||||||
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
|
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
|
||||||
|
RLAPI void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors (vertex in counter-clockwise order!)
|
||||||
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
|
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
|
||||||
RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
|
RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
|
||||||
RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
|
RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
|
||||||
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon of n sides
|
||||||
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
|
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
|
||||||
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
|
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
|
||||||
|
|
||||||
|
|
@ -1327,14 +1330,14 @@ RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vect
|
||||||
RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
|
RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
|
||||||
RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline
|
RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline
|
||||||
RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom
|
RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom
|
||||||
RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier
|
RLAPI Vector2 GetSplinePointBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier
|
||||||
RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier
|
RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier
|
||||||
|
|
||||||
// Basic shapes collision detection functions
|
// Basic shapes collision detection functions
|
||||||
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
|
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
|
||||||
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
|
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
|
||||||
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
|
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
|
||||||
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2]
|
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created between two points [p1] and [p2]
|
||||||
RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
|
RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
|
||||||
RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
|
RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
|
||||||
RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
|
RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
|
||||||
|
|
@ -1355,11 +1358,11 @@ RLAPI Image LoadImageAnim(const char *fileName, int *frames);
|
||||||
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
|
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
|
||||||
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||||
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
|
||||||
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
|
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer (screenshot)
|
||||||
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
||||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree()
|
||||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||||
|
|
||||||
// Image generation functions
|
// Image generation functions
|
||||||
|
|
@ -1401,7 +1404,7 @@ RLAPI void ImageRotateCCW(Image *image);
|
||||||
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||||
RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
|
RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
|
||||||
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
|
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
|
||||||
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
|
RLAPI void ImageColorContrast(Image *image, int contrast); // Modify image color: contrast (-100 to 100)
|
||||||
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||||
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
|
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
|
||||||
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
|
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
|
||||||
|
|
@ -1426,9 +1429,10 @@ RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color c
|
||||||
RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
|
RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
|
||||||
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
|
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
|
||||||
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
|
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
|
||||||
RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image
|
RLAPI void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle lines within an image
|
||||||
|
RLAPI void ImageDrawRectangleLinesEx(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image with extended parameters
|
||||||
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 ImageDrawTriangleGradient(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, const 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, const 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
|
||||||
|
|
@ -1460,7 +1464,7 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
|
||||||
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
||||||
RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
|
RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
|
||||||
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||||
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
|
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a texture (or part of it) that stretches or shrinks nicely
|
||||||
|
|
||||||
// Color/pixel related functions
|
// Color/pixel related functions
|
||||||
RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal
|
RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal
|
||||||
|
|
@ -1504,7 +1508,7 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple characters (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
|
|
@ -1528,19 +1532,22 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size);
|
||||||
|
|
||||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||||
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
||||||
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
|
// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree()
|
||||||
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||||
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||||
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text strings are equal
|
||||||
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
||||||
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
|
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
|
||||||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||||
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||||
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string (WARNING: memory must be freed!)
|
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings (WARNING: memory must be freed!)
|
RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||||
|
RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||||
|
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position
|
||||||
|
RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||||
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||||
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
||||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
||||||
|
|
@ -1573,9 +1580,9 @@ RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slice
|
||||||
RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
|
RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
|
||||||
RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
|
RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
|
||||||
RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
|
RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
|
||||||
RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos
|
RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int slices, Color color); // Draw a cylinder wires with base at startPos and top at endPos
|
||||||
RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
|
RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
|
||||||
RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
|
RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
|
||||||
RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
|
RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
|
||||||
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
|
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
|
||||||
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
||||||
|
|
@ -1596,8 +1603,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
||||||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
|
||||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
|
||||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||||
|
|
@ -1667,15 +1672,15 @@ RLAPI float GetMasterVolume(void); // Get mas
|
||||||
// Wave/Sound loading/unloading functions
|
// Wave/Sound loading/unloading functions
|
||||||
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
|
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
|
||||||
RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
|
RLAPI bool IsWaveValid(Wave wave); // Check if wave data is valid (data loaded and parameters)
|
||||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
|
RLAPI Sound LoadSoundAlias(Sound source); // Load sound alias, 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); // Check 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 (default data format: 32 bit float, stereo)
|
RLAPI void UpdateSound(Sound sound, const void *data, int frameCount); // Update sound buffer with new data (default data format: 32 bit float, stereo)
|
||||||
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 sound alias (does not deallocate sample data)
|
||||||
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
|
||||||
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
|
||||||
|
|
||||||
|
|
@ -1697,24 +1702,24 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
|
||||||
// Music management functions
|
// Music management functions
|
||||||
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||||
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
|
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
|
||||||
RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
|
RLAPI bool IsMusicValid(Music music); // Check if a music stream is valid (context and buffers initialized)
|
||||||
RLAPI void UnloadMusicStream(Music music); // Unload music stream
|
RLAPI void UnloadMusicStream(Music music); // Unload music stream
|
||||||
RLAPI void PlayMusicStream(Music music); // Start music playing
|
RLAPI void PlayMusicStream(Music music); // Start music playing
|
||||||
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
|
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
|
||||||
RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming
|
RLAPI void UpdateMusicStream(Music music); // Update buffers for music streaming
|
||||||
RLAPI void StopMusicStream(Music music); // Stop music playing
|
RLAPI void StopMusicStream(Music music); // Stop music playing
|
||||||
RLAPI void PauseMusicStream(Music music); // Pause music playing
|
RLAPI void PauseMusicStream(Music music); // Pause music playing
|
||||||
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
|
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
||||||
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for music (1.0 is base level)
|
||||||
RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right)
|
RLAPI void SetMusicPan(Music music, float pan); // Set pan for music (-1.0 left, 0.0 center, 1.0 right)
|
||||||
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||||
|
|
||||||
// AudioStream management functions
|
// AudioStream management functions
|
||||||
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
||||||
RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
|
RLAPI bool IsAudioStreamValid(AudioStream stream); // Check if an audio stream is valid (buffers initialized)
|
||||||
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
||||||
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
|
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
|
||||||
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||||
|
|
@ -1725,7 +1730,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i
|
||||||
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
||||||
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||||
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)
|
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right)
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
GLFW_ICON ICON "raylib.ico"
|
GLFW_ICON ICON "raylib.ico"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 5,5,0,0
|
FILEVERSION 6,0,0,0
|
||||||
PRODUCTVERSION 5,5,0,0
|
PRODUCTVERSION 6,0,0,0
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
@ -11,12 +11,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "raylib technologies"
|
VALUE "CompanyName", "raylib technologies"
|
||||||
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
VALUE "FileDescription", "raylib application (www.raylib.com)"
|
||||||
VALUE "FileVersion", "5.5.0"
|
VALUE "FileVersion", "6.0.0"
|
||||||
VALUE "InternalName", "raylib"
|
VALUE "InternalName", "raylib"
|
||||||
VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)"
|
VALUE "LegalCopyright", "(c) 2026 Ramon Santamaria (@raysan5)"
|
||||||
VALUE "OriginalFilename", "raylib"
|
VALUE "OriginalFilename", "raylib"
|
||||||
VALUE "ProductName", "raylib app"
|
VALUE "ProductName", "raylib app"
|
||||||
VALUE "ProductVersion", "5.5.0"
|
VALUE "ProductVersion", "6.0.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
*
|
*
|
||||||
* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
|
* raymath v2.0 - Math functions to work with Vector2, Vector3, Vector4, Matrix and Quaternions
|
||||||
*
|
*
|
||||||
* CONVENTIONS:
|
* CONVENTIONS:
|
||||||
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
|
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
* - Functions use always a "result" variable for return (except C++ operators)
|
* - Functions use always a "result" variable for return (except C++ operators)
|
||||||
* - Functions are always defined inline
|
* - Functions are always defined inline
|
||||||
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
|
||||||
* - No compound literals used to make sure libray is compatible with C++
|
* - No compound literals used to make sure the library is compatible with C++
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define RAYMATH_IMPLEMENTATION
|
* #define RAYMATH_IMPLEMENTATION
|
||||||
|
|
@ -183,7 +183,7 @@ typedef struct float16 {
|
||||||
#if RAYMATH_USE_SIMD_INTRINSICS
|
#if RAYMATH_USE_SIMD_INTRINSICS
|
||||||
// SIMD is used on the most costly raymath function MatrixMultiply()
|
// SIMD is used on the most costly raymath function MatrixMultiply()
|
||||||
// NOTE: Only SSE intrinsics support implemented
|
// NOTE: Only SSE intrinsics support implemented
|
||||||
// TODO: Consider support for other SIMD instrinsics:
|
// TODO: Consider support for other SIMD intrinsics:
|
||||||
// - SSEx, AVX, AVX2, FMA, NEON, RVV
|
// - SSEx, AVX, AVX2, FMA, NEON, RVV
|
||||||
/*
|
/*
|
||||||
#if defined(__SSE4_2__)
|
#if defined(__SSE4_2__)
|
||||||
|
|
@ -1151,7 +1151,7 @@ RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
|
||||||
// Create quaternion from source point
|
// Create quaternion from source point
|
||||||
Quaternion quat = { source.x, source.y, source.z, 1.0f };
|
Quaternion quat = { source.x, source.y, source.z, 1.0f };
|
||||||
|
|
||||||
// Multiply quat point by unprojecte matrix
|
// Multiply quat point by unprojected matrix
|
||||||
Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
|
Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
|
||||||
matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
|
matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
|
||||||
matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
|
matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
|
||||||
|
|
@ -1264,19 +1264,21 @@ RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Vector4 math
|
// Module Functions Definition - Vector4 math
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
// Get vector zero
|
||||||
RMAPI Vector4 Vector4Zero(void)
|
RMAPI Vector4 Vector4Zero(void)
|
||||||
{
|
{
|
||||||
Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f };
|
Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get vector one
|
||||||
RMAPI Vector4 Vector4One(void)
|
RMAPI Vector4 Vector4One(void)
|
||||||
{
|
{
|
||||||
Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f };
|
Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add two vectors
|
||||||
RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
|
RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
|
||||||
{
|
{
|
||||||
Vector4 result = {
|
Vector4 result = {
|
||||||
|
|
@ -1288,6 +1290,7 @@ RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add value to vector components
|
||||||
RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
|
RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
|
||||||
{
|
{
|
||||||
Vector4 result = {
|
Vector4 result = {
|
||||||
|
|
@ -1299,6 +1302,7 @@ RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Substract vectors
|
||||||
RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
|
RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
|
||||||
{
|
{
|
||||||
Vector4 result = {
|
Vector4 result = {
|
||||||
|
|
@ -1310,6 +1314,7 @@ RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Substract value from vector components
|
||||||
RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
|
RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
|
||||||
{
|
{
|
||||||
Vector4 result = {
|
Vector4 result = {
|
||||||
|
|
@ -1321,18 +1326,21 @@ RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vector length
|
||||||
RMAPI float Vector4Length(Vector4 v)
|
RMAPI float Vector4Length(Vector4 v)
|
||||||
{
|
{
|
||||||
float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
|
float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vector square length
|
||||||
RMAPI float Vector4LengthSqr(Vector4 v)
|
RMAPI float Vector4LengthSqr(Vector4 v)
|
||||||
{
|
{
|
||||||
float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w);
|
float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vectors dot product
|
||||||
RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2)
|
RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2)
|
||||||
{
|
{
|
||||||
float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w);
|
float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w);
|
||||||
|
|
@ -1358,6 +1366,7 @@ RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale vector components by value (multiply)
|
||||||
RMAPI Vector4 Vector4Scale(Vector4 v, float scale)
|
RMAPI Vector4 Vector4Scale(Vector4 v, float scale)
|
||||||
{
|
{
|
||||||
Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale };
|
Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale };
|
||||||
|
|
@ -1753,6 +1762,7 @@ RMAPI Matrix MatrixMultiply(Matrix left, Matrix right)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiply matrix components by value
|
||||||
RMAPI Matrix MatrixMultiplyValue(Matrix left, float value)
|
RMAPI Matrix MatrixMultiplyValue(Matrix left, float value)
|
||||||
{
|
{
|
||||||
Matrix result = {
|
Matrix result = {
|
||||||
|
|
@ -2495,19 +2505,14 @@ RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
||||||
{
|
{
|
||||||
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
|
float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
|
||||||
|
|
||||||
if (axisLength != 0.0f)
|
if (length != 0.0f)
|
||||||
{
|
{
|
||||||
angle *= 0.5f;
|
angle *= 0.5f;
|
||||||
|
|
||||||
float length = 0.0f;
|
|
||||||
float ilength = 0.0f;
|
|
||||||
|
|
||||||
// Vector3Normalize(axis)
|
// Vector3Normalize(axis)
|
||||||
length = axisLength;
|
float ilength = 1.0f/length;
|
||||||
if (length == 0.0f) length = 1.0f;
|
|
||||||
ilength = 1.0f/length;
|
|
||||||
axis.x *= ilength;
|
axis.x *= ilength;
|
||||||
axis.y *= ilength;
|
axis.y *= ilength;
|
||||||
axis.z *= ilength;
|
axis.z *= ilength;
|
||||||
|
|
@ -2797,6 +2802,11 @@ inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Vector2 operator * (const float& lhs, const Vector2& rhs)
|
||||||
|
{
|
||||||
|
return Vector2Scale(rhs, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
inline Vector2 operator * (const Vector2& lhs, const float& rhs)
|
inline Vector2 operator * (const Vector2& lhs, const float& rhs)
|
||||||
{
|
{
|
||||||
return Vector2Scale(lhs, rhs);
|
return Vector2Scale(lhs, rhs);
|
||||||
|
|
@ -2891,6 +2901,11 @@ inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Vector3 operator * (const float& lhs, const Vector3& rhs)
|
||||||
|
{
|
||||||
|
return Vector3Scale(rhs, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
inline Vector3 operator * (const Vector3& lhs, const float& rhs)
|
inline Vector3 operator * (const Vector3& lhs, const float& rhs)
|
||||||
{
|
{
|
||||||
return Vector3Scale(lhs, rhs);
|
return Vector3Scale(lhs, rhs);
|
||||||
|
|
@ -2986,6 +3001,11 @@ inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Vector4 operator * (const float& lhs, const Vector4& rhs)
|
||||||
|
{
|
||||||
|
return Vector4Scale(rhs, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
inline Vector4 operator * (const Vector4& lhs, const float& rhs)
|
inline Vector4 operator * (const Vector4& lhs, const float& rhs)
|
||||||
{
|
{
|
||||||
return Vector4Scale(lhs, rhs);
|
return Vector4Scale(lhs, rhs);
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
Vector3 position; // Camera position
|
Vector3 position; // Camera position
|
||||||
Vector3 target; // Camera target it looks-at
|
Vector3 target; // Camera target it looks-at
|
||||||
Vector3 up; // Camera up vector (rotation over its axis)
|
Vector3 up; // Camera up vector (rotation over its axis)
|
||||||
float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
|
float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
|
||||||
int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
|
int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
|
||||||
} Camera3D;
|
} Camera3D;
|
||||||
|
|
||||||
|
|
@ -352,7 +352,7 @@ void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget)
|
||||||
// Rotates the camera around its right vector, pitch is "looking up and down"
|
// Rotates the camera around its right vector, pitch is "looking up and down"
|
||||||
// - lockView prevents camera overrotation (aka "somersaults")
|
// - lockView prevents camera overrotation (aka "somersaults")
|
||||||
// - rotateAroundTarget defines if rotation is around target or around its position
|
// - rotateAroundTarget defines if rotation is around target or around its position
|
||||||
// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE)
|
// - rotateUp rotates the up direction as well (typically only useful in CAMERA_FREE)
|
||||||
// NOTE: [angle] must be provided in radians
|
// NOTE: [angle] must be provided in radians
|
||||||
void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
|
void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
230
src/rcore.c
230
src/rcore.c
|
|
@ -35,31 +35,31 @@
|
||||||
* - Memory framebuffer output, using software renderer, no OS required
|
* - Memory framebuffer output, using software renderer, no OS required
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_CAMERA_SYSTEM
|
* #define SUPPORT_CAMERA_SYSTEM 1
|
||||||
* Camera module is included (rcamera.h) and multiple predefined cameras are available:
|
* Camera module is included (rcamera.h) and multiple predefined cameras are available:
|
||||||
* free, 1st/3rd person, orbital, custom
|
* free, 1st/3rd person, orbital, custom
|
||||||
*
|
*
|
||||||
* #define SUPPORT_GESTURES_SYSTEM
|
* #define SUPPORT_GESTURES_SYSTEM 1
|
||||||
* Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
* Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
|
||||||
*
|
*
|
||||||
* #define SUPPORT_MOUSE_GESTURES
|
* #define SUPPORT_MOUSE_GESTURES 1
|
||||||
* Mouse gestures are directly mapped like touches and processed by gestures system
|
* Mouse gestures are directly mapped like touches and processed by gestures system
|
||||||
*
|
*
|
||||||
* #define SUPPORT_BUSY_WAIT_LOOP
|
* #define SUPPORT_BUSY_WAIT_LOOP 1
|
||||||
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
||||||
*
|
*
|
||||||
* #define SUPPORT_PARTIALBUSY_WAIT_LOOP
|
* #define SUPPORT_PARTIALBUSY_WAIT_LOOP 0
|
||||||
* Use a partial-busy wait loop, in this case frame sleeps for most of the time and runs a busy-wait-loop at the end
|
* Use a partial-busy wait loop, in this case frame sleeps for most of the time and runs a busy-wait-loop at the end
|
||||||
*
|
*
|
||||||
* #define SUPPORT_SCREEN_CAPTURE
|
* #define SUPPORT_SCREEN_CAPTURE 1
|
||||||
* Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
* Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
|
||||||
*
|
*
|
||||||
* #define SUPPORT_COMPRESSION_API
|
* #define SUPPORT_COMPRESSION_API 1
|
||||||
* Support CompressData() and DecompressData() functions, those functions use zlib implementation
|
* Support CompressData() and DecompressData() functions, those functions use zlib implementation
|
||||||
* provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module
|
* provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module
|
||||||
* for linkage
|
* for linkage
|
||||||
*
|
*
|
||||||
* #define SUPPORT_AUTOMATION_EVENTS
|
* #define SUPPORT_AUTOMATION_EVENTS 1
|
||||||
* Support automatic events recording and playing, useful for automated testing systems or AI based game playing
|
* Support automatic events recording and playing, useful for automated testing systems or AI based game playing
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
|
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: srand(), rand(), atexit(), exit()
|
#include <stdlib.h> // Required for: srand(), rand(), exit()
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()]
|
#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()]
|
||||||
#include <string.h> // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat()
|
#include <string.h> // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat()
|
||||||
#include <stdarg.h> // Required for: va_list, va_start(), va_end() [Used in TraceLog()]
|
#include <stdarg.h> // Required for: va_list, va_start(), va_end() [Used in TraceLog()]
|
||||||
|
|
@ -267,15 +267,18 @@
|
||||||
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// File and directory scan filters
|
||||||
|
// NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||||
|
// WARNING: Custom file filters can be specified but following raylib IsFileExtension() convention: ".png;.wav;.glb"
|
||||||
#ifndef FILE_FILTER_TAG_ALL
|
#ifndef FILE_FILTER_TAG_ALL
|
||||||
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan
|
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on scan
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
||||||
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan
|
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on scan (no directories)
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
||||||
#define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan
|
#define FILE_FILTER_TAG_DIR_ONLY "DIRS*" // Filter to include only directories on scan
|
||||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
#endif
|
||||||
|
|
||||||
// Flags bitwise operation macros
|
// Flags bitwise operation macros
|
||||||
#define FLAG_SET(n, f) ((n) |= (f))
|
#define FLAG_SET(n, f) ((n) |= (f))
|
||||||
|
|
@ -304,7 +307,7 @@ typedef struct CoreData {
|
||||||
Size screen; // Screen current width and height
|
Size screen; // Screen current width and height
|
||||||
Point position; // Window current position
|
Point position; // Window current position
|
||||||
Size previousScreen; // Screen previous width and height (required on fullscreen/borderless-windowed toggle)
|
Size previousScreen; // Screen previous width and height (required on fullscreen/borderless-windowed toggle)
|
||||||
Point previousPosition; // Window previous position (required on fullscreeen/borderless-windowed toggle)
|
Point previousPosition; // Window previous position (required on fullscreen/borderless-windowed toggle)
|
||||||
Size render; // Screen framebuffer width and height
|
Size render; // Screen framebuffer width and height
|
||||||
Point renderOffset; // Screen framebuffer render offset (Not required anymore?)
|
Point renderOffset; // Screen framebuffer render offset (Not required anymore?)
|
||||||
Size currentFbo; // Current framebuffer render width and height (depends on active render texture)
|
Size currentFbo; // Current framebuffer render width and height (depends on active render texture)
|
||||||
|
|
@ -326,7 +329,7 @@ typedef struct CoreData {
|
||||||
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
|
||||||
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
|
||||||
|
|
||||||
// NOTE: Since key press logic involves comparing previous vs currrent key state,
|
// NOTE: Since key press logic involves comparing previous vs current key state,
|
||||||
// key repeats needs to be handled specially
|
// key repeats needs to be handled specially
|
||||||
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame
|
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame
|
||||||
|
|
||||||
|
|
@ -376,14 +379,14 @@ typedef struct CoreData {
|
||||||
} Gamepad;
|
} Gamepad;
|
||||||
} Input;
|
} Input;
|
||||||
struct {
|
struct {
|
||||||
double current; // Current time measure
|
double current; // Current time measure (seconds)
|
||||||
double previous; // Previous time measure
|
double previous; // Previous time measure (seconds)
|
||||||
double update; // Time measure for frame update
|
double update; // Time measure for frame update (seconds)
|
||||||
double draw; // Time measure for frame draw
|
double draw; // Time measure for frame draw (seconds)
|
||||||
double frame; // Time measure for one frame
|
double frame; // Time measure for one frame (seconds)
|
||||||
double target; // Desired time for one frame, if 0 not applied
|
double target; // Desired time for one frame, if 0 not applied (seconds)
|
||||||
unsigned long long int base; // Base time measure for hi-res timer (PLATFORM_ANDROID, PLATFORM_DRM)
|
unsigned long long base; // Base time measure for hi-res timer (ticks or nanoseconds)
|
||||||
unsigned int frameCounter; // Frame counter
|
unsigned int frameCounter; // Frame counter (frames)
|
||||||
|
|
||||||
} Time;
|
} Time;
|
||||||
} CoreData;
|
} CoreData;
|
||||||
|
|
@ -439,18 +442,6 @@ typedef enum AutomationEventType {
|
||||||
ACTION_SETTARGETFPS // param[0]: fps
|
ACTION_SETTARGETFPS // param[0]: fps
|
||||||
} AutomationEventType;
|
} AutomationEventType;
|
||||||
|
|
||||||
// Event type to config events flags
|
|
||||||
// WARNING: Not used at the moment
|
|
||||||
typedef enum {
|
|
||||||
EVENT_INPUT_KEYBOARD = 0,
|
|
||||||
EVENT_INPUT_MOUSE = 1,
|
|
||||||
EVENT_INPUT_GAMEPAD = 2,
|
|
||||||
EVENT_INPUT_TOUCH = 4,
|
|
||||||
EVENT_INPUT_GESTURE = 8,
|
|
||||||
EVENT_WINDOW = 16,
|
|
||||||
EVENT_CUSTOM = 32
|
|
||||||
} EventType;
|
|
||||||
|
|
||||||
// Event type name strings, required for export
|
// Event type name strings, required for export
|
||||||
static const char *autoEventTypeName[] = {
|
static const char *autoEventTypeName[] = {
|
||||||
"EVENT_NONE",
|
"EVENT_NONE",
|
||||||
|
|
@ -479,16 +470,6 @@ static const char *autoEventTypeName[] = {
|
||||||
"ACTION_SETTARGETFPS"
|
"ACTION_SETTARGETFPS"
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
// Automation event (24 bytes)
|
|
||||||
// NOTE: Opaque struct, internal to raylib
|
|
||||||
struct AutomationEvent {
|
|
||||||
unsigned int frame; // Event frame
|
|
||||||
unsigned int type; // Event type (AutomationEventType)
|
|
||||||
int params[4]; // Event parameters (if required)
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer
|
static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer
|
||||||
static bool automationEventRecording = false; // Recording automation events flag
|
static bool automationEventRecording = false; // Recording automation events flag
|
||||||
//static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing
|
//static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing
|
||||||
|
|
@ -711,7 +692,7 @@ void InitWindow(int width, int height, const char *title)
|
||||||
Rectangle rec = GetFontDefault().recs[95];
|
Rectangle rec = GetFontDefault().recs[95];
|
||||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT))
|
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT))
|
||||||
{
|
{
|
||||||
// NOTE: Try to maxime rec padding to avoid pixel bleeding on MSAA filtering
|
// NOTE: Try to maximize rec padding to avoid pixel bleeding on MSAA filtering
|
||||||
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -821,7 +802,7 @@ int GetRenderWidth(void)
|
||||||
{
|
{
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
|
if (CORE.Window.usingFbo) width = CORE.Window.currentFbo.width;
|
||||||
else width = CORE.Window.render.width;
|
else width = CORE.Window.render.width;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
|
@ -832,7 +813,7 @@ int GetRenderHeight(void)
|
||||||
{
|
{
|
||||||
int height = 0;
|
int height = 0;
|
||||||
|
|
||||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
|
if (CORE.Window.usingFbo) height = CORE.Window.currentFbo.height;
|
||||||
else height = CORE.Window.render.height;
|
else height = CORE.Window.render.height;
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
|
|
@ -866,14 +847,14 @@ bool IsCursorOnScreen(void)
|
||||||
// Module Functions Definition: Screen Drawing
|
// Module Functions Definition: Screen Drawing
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Set background color (framebuffer clear color)
|
// Clear background (framebuffer) to color
|
||||||
void ClearBackground(Color color)
|
void ClearBackground(Color color)
|
||||||
{
|
{
|
||||||
rlClearColor(color.r, color.g, color.b, color.a); // Set clear color
|
rlClearColor(color.r, color.g, color.b, color.a); // Set clear color
|
||||||
rlClearScreenBuffers(); // Clear current framebuffers
|
rlClearScreenBuffers(); // Clear current framebuffers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup canvas (framebuffer) to start drawing
|
// Begin canvas (framebuffer) drawing
|
||||||
void BeginDrawing(void)
|
void BeginDrawing(void)
|
||||||
{
|
{
|
||||||
// WARNING: Previously to BeginDrawing() other render textures drawing could happen,
|
// WARNING: Previously to BeginDrawing() other render textures drawing could happen,
|
||||||
|
|
@ -890,7 +871,7 @@ void BeginDrawing(void)
|
||||||
// NOTE: Not required with OpenGL 3.3+
|
// NOTE: Not required with OpenGL 3.3+
|
||||||
}
|
}
|
||||||
|
|
||||||
// End canvas drawing and swap buffers (double buffering)
|
// End canvas (framebuffer) drawing and swap buffers (double buffering)
|
||||||
void EndDrawing(void)
|
void EndDrawing(void)
|
||||||
{
|
{
|
||||||
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
||||||
|
|
@ -946,7 +927,7 @@ void BeginMode2D(Camera2D camera)
|
||||||
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
|
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ends 2D mode with custom camera
|
// End 2D mode with custom camera
|
||||||
void EndMode2D(void)
|
void EndMode2D(void)
|
||||||
{
|
{
|
||||||
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
||||||
|
|
@ -995,7 +976,7 @@ void BeginMode3D(Camera camera)
|
||||||
rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
|
rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ends 3D mode and returns to default 2D orthographic mode
|
// End 3D mode and returns to default 2D orthographic mode
|
||||||
void EndMode3D(void)
|
void EndMode3D(void)
|
||||||
{
|
{
|
||||||
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
||||||
|
|
@ -1042,7 +1023,7 @@ void BeginTextureMode(RenderTexture2D target)
|
||||||
CORE.Window.usingFbo = true;
|
CORE.Window.usingFbo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ends drawing to render texture
|
// End drawing to render texture
|
||||||
void EndTextureMode(void)
|
void EndTextureMode(void)
|
||||||
{
|
{
|
||||||
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
||||||
|
|
@ -1227,7 +1208,7 @@ void UnloadVrStereoConfig(VrStereoConfig config)
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Load shader from files and bind default locations
|
// Load shader from files and bind default locations
|
||||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
// NOTE: If shader filename is NULL, using default vertex/fragment shaders
|
||||||
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
Shader shader = { 0 };
|
||||||
|
|
@ -1511,7 +1492,7 @@ Matrix GetCameraMatrix2D(Camera2D camera)
|
||||||
return matTransform;
|
return matTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the screen space position from a 3d world space position
|
// Get screen space position from a 3d world space position
|
||||||
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
{
|
{
|
||||||
Vector2 screenPosition = GetWorldToScreenEx(position, camera, GetScreenWidth(), GetScreenHeight());
|
Vector2 screenPosition = GetWorldToScreenEx(position, camera, GetScreenWidth(), GetScreenHeight());
|
||||||
|
|
@ -1519,7 +1500,7 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
return screenPosition;
|
return screenPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get size position for a 3d world space position (useful for texture drawing)
|
// Get sized screen space position for a 3d world space position (useful for texture drawing)
|
||||||
Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height)
|
Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height)
|
||||||
{
|
{
|
||||||
// Calculate projection matrix (from perspective instead of frustum
|
// Calculate projection matrix (from perspective instead of frustum
|
||||||
|
|
@ -1561,7 +1542,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh
|
||||||
return screenPosition;
|
return screenPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the screen space position for a 2d camera world space position
|
// Get screen space position for a 2d camera world space position
|
||||||
Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
|
Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
|
||||||
{
|
{
|
||||||
Matrix matCamera = GetCameraMatrix2D(camera);
|
Matrix matCamera = GetCameraMatrix2D(camera);
|
||||||
|
|
@ -1570,7 +1551,7 @@ Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
|
||||||
return (Vector2){ transform.x, transform.y };
|
return (Vector2){ transform.x, transform.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the world space position for a 2d camera screen space position
|
// Get world space position for a 2d camera screen space position
|
||||||
Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera)
|
Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera)
|
||||||
{
|
{
|
||||||
Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera));
|
Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera));
|
||||||
|
|
@ -1621,8 +1602,8 @@ int GetFPS(void)
|
||||||
for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0;
|
for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpsFrame == 0) return 0;
|
if (fpsFrame != 0)
|
||||||
|
{
|
||||||
if ((GetTime() - last) > FPS_STEP)
|
if ((GetTime() - last) > FPS_STEP)
|
||||||
{
|
{
|
||||||
last = (float)GetTime();
|
last = (float)GetTime();
|
||||||
|
|
@ -1633,6 +1614,8 @@ int GetFPS(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fps = (int)roundf(1.0f/average);
|
fps = (int)roundf(1.0f/average);
|
||||||
|
}
|
||||||
|
else fps = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return fps;
|
return fps;
|
||||||
|
|
@ -1752,9 +1735,9 @@ int GetRandomValue(int min, int max)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Rejection sampling to get a uniform integer in [min, max]
|
// Rejection sampling to get a uniform integer in [min, max]
|
||||||
unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results
|
unsigned long c = (unsigned long)RAND_MAX + 1UL; // Number of possible results
|
||||||
unsigned long m = (unsigned long)range; // size of the target interval
|
unsigned long m = (unsigned long)range; // Size of the target interval
|
||||||
unsigned long t = c - (c%m); // largest multiple of m <= c
|
unsigned long t = c - (c%m); // Largest multiple of m <= c
|
||||||
unsigned long r = 0;
|
unsigned long r = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|
@ -1999,7 +1982,7 @@ unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
||||||
{
|
{
|
||||||
*dataSize = (int)count;
|
*dataSize = (int)count;
|
||||||
|
|
||||||
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count);
|
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, *dataSize, size);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2023,9 +2006,9 @@ void UnloadFileData(unsigned char *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data to file from buffer
|
// Save data to file from buffer
|
||||||
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
bool SaveFileData(const char *fileName, const void *data, int dataSize)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2043,20 +2026,20 @@ bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||||
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int closed = fclose(file);
|
||||||
if (result == 0) success = true;
|
if (closed == 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export data to code (.h), returns true on success
|
// Export data to code (.h), returns true on success
|
||||||
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -2096,14 +2079,14 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load text data from file, returns a '\0' terminated string
|
// Load text data from file, returns a '\0' terminated string
|
||||||
|
|
@ -2166,7 +2149,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, const char *text)
|
bool SaveFileText(const char *fileName, const char *text)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (fileName != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2181,14 +2164,14 @@ bool SaveFileText(const char *fileName, const char *text)
|
||||||
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
|
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
|
||||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
|
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
|
||||||
|
|
||||||
int result = fclose(file);
|
int closed = fclose(file);
|
||||||
if (result == 0) success = true;
|
if (closed == 0) result = true;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// File access custom callbacks
|
// File access custom callbacks
|
||||||
|
|
@ -2278,10 +2261,11 @@ int FileMove(const char *srcPath, const char *dstPath)
|
||||||
|
|
||||||
if (FileExists(srcPath))
|
if (FileExists(srcPath))
|
||||||
{
|
{
|
||||||
if (FileCopy(srcPath, dstPath) == 0)
|
FileCopy(srcPath, dstPath);
|
||||||
result = FileRemove(srcPath);
|
|
||||||
else
|
// Make sure file has been correctly copied before removing
|
||||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath);
|
if (FileExists(dstPath) && (GetFileLength(srcPath) == GetFileLength(dstPath))) result = FileRemove(srcPath);
|
||||||
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath);
|
||||||
|
|
||||||
|
|
@ -2300,7 +2284,7 @@ int FileTextReplace(const char *fileName, const char *search, const char *replac
|
||||||
if (FileExists(fileName))
|
if (FileExists(fileName))
|
||||||
{
|
{
|
||||||
fileText = LoadFileText(fileName);
|
fileText = LoadFileText(fileName);
|
||||||
fileTextUpdated = TextReplace(fileText, search, replacement);
|
fileTextUpdated = TextReplaceAlloc(fileText, search, replacement);
|
||||||
result = SaveFileText(fileName, fileTextUpdated);
|
result = SaveFileText(fileName, fileTextUpdated);
|
||||||
MemFree(fileTextUpdated);
|
MemFree(fileTextUpdated);
|
||||||
UnloadFileText(fileText);
|
UnloadFileText(fileText);
|
||||||
|
|
@ -2359,8 +2343,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
||||||
{
|
{
|
||||||
int fileExtLength = (int)strlen(fileExt);
|
int fileExtLength = (int)strlen(fileExt);
|
||||||
char fileExtLower[16] = { 0 };
|
char fileExtLower[16] = { 0 };
|
||||||
char *fileExtLowerPtr = fileExtLower;
|
for (int i = 0; (i < fileExtLength) && (i < 15); i++)
|
||||||
for (int i = 0; (i < fileExtLength) && (i < 16); i++)
|
|
||||||
{
|
{
|
||||||
// Copy and convert to lower-case
|
// Copy and convert to lower-case
|
||||||
if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32;
|
if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32;
|
||||||
|
|
@ -2371,7 +2354,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
||||||
int extLength = (int)strlen(ext);
|
int extLength = (int)strlen(ext);
|
||||||
char *extList = (char *)RL_CALLOC(extLength + 1, 1);
|
char *extList = (char *)RL_CALLOC(extLength + 1, 1);
|
||||||
char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 };
|
char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 };
|
||||||
strncpy(extList, ext, extLength);
|
memcpy(extList, ext, extLength);
|
||||||
extListPtrs[0] = extList;
|
extListPtrs[0] = extList;
|
||||||
|
|
||||||
for (int i = 0; i < extLength; i++)
|
for (int i = 0; i < extLength; i++)
|
||||||
|
|
@ -2380,19 +2363,23 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
||||||
if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32;
|
if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32;
|
||||||
|
|
||||||
// Get pointer to next extension and add null-terminator
|
// Get pointer to next extension and add null-terminator
|
||||||
if ((extList[i] == ';') && (extCount < (MAX_FILE_EXTENSIONS - 1)))
|
if (extList[i] == ';')
|
||||||
{
|
{
|
||||||
extList[i] = '\0';
|
extList[i] = '\0';
|
||||||
|
|
||||||
|
if (extCount < MAX_FILE_EXTENSIONS)
|
||||||
|
{
|
||||||
extListPtrs[extCount] = extList + i + 1;
|
extListPtrs[extCount] = extList + i + 1;
|
||||||
extCount++;
|
extCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < extCount; i++)
|
for (int i = 0; i < extCount; i++)
|
||||||
{
|
{
|
||||||
// Consider the case where extension provided
|
// Consider the case where extension provided
|
||||||
// does not start with the '.'
|
// does not start with the '.'
|
||||||
fileExtLowerPtr = fileExtLower;
|
char *fileExtLowerPtr = fileExtLower;
|
||||||
if (extListPtrs[i][0] != '.') fileExtLowerPtr++;
|
if (extListPtrs[i][0] != '.') fileExtLowerPtr++;
|
||||||
|
|
||||||
if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0)
|
if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0)
|
||||||
|
|
@ -2511,9 +2498,9 @@ const char *GetFileNameWithoutExt(const char *filePath)
|
||||||
if (filePath != NULL)
|
if (filePath != NULL)
|
||||||
{
|
{
|
||||||
strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path
|
strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path
|
||||||
int fileNameLenght = (int)strlen(fileName); // Get size in bytes
|
int fileNameLength = (int)strlen(fileName); // Get size in bytes
|
||||||
|
|
||||||
for (int i = fileNameLenght; i > 0; i--) // Reverse search '.'
|
for (int i = fileNameLength; i > 0; i--) // Reverse search '.'
|
||||||
{
|
{
|
||||||
if (fileName[i] == '.')
|
if (fileName[i] == '.')
|
||||||
{
|
{
|
||||||
|
|
@ -2605,7 +2592,7 @@ const char *GetWorkingDirectory(void)
|
||||||
static char currentDir[MAX_FILEPATH_LENGTH] = { 0 };
|
static char currentDir[MAX_FILEPATH_LENGTH] = { 0 };
|
||||||
memset(currentDir, 0, MAX_FILEPATH_LENGTH);
|
memset(currentDir, 0, MAX_FILEPATH_LENGTH);
|
||||||
|
|
||||||
char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH - 1);
|
char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
@ -2720,17 +2707,18 @@ const char *GetApplicationDirectory(void)
|
||||||
|
|
||||||
// Load directory filepaths
|
// Load directory filepaths
|
||||||
// NOTE: Base path is prepended to the scanned filepaths
|
// NOTE: Base path is prepended to the scanned filepaths
|
||||||
// WARNING: Directory is scanned twice, first time to get files count
|
// WARNING: Directory is scanned twice, first time to get paths count
|
||||||
// No recursive scanning is done!
|
// Scanneed files and directories, no recursive/subdirs scanning
|
||||||
FilePathList LoadDirectoryFiles(const char *dirPath)
|
FilePathList LoadDirectoryFiles(const char *dirPath)
|
||||||
{
|
{
|
||||||
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load directory filepaths with extension filtering and recursive directory scan
|
// Load directory filepaths with extension filtering and recursive directory scan
|
||||||
// Use 'DIR*' to include directories on directory scan
|
// Use "*.*" to include all files and directories on scan
|
||||||
// Use '*.*' to include all file types and directories on directory scan
|
// Use "FILES*" to include only files on scan
|
||||||
// WARNING: Directory is scanned twice, first time to get files count
|
// Use "DIRS*" to include only directories on scan
|
||||||
|
// WARNING: Directory is scanned twice, first time to get paths count
|
||||||
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
||||||
{
|
{
|
||||||
FilePathList files = { 0 };
|
FilePathList files = { 0 };
|
||||||
|
|
@ -2951,9 +2939,9 @@ unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, b
|
||||||
{
|
{
|
||||||
// Construct new path from our base path
|
// Construct new path from our base path
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, entity->d_name);
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, entity->d_name);
|
||||||
#else
|
#else
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, entity->d_name);
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, entity->d_name);
|
||||||
#endif
|
#endif
|
||||||
// Don't add to count if path too long
|
// Don't add to count if path too long
|
||||||
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
||||||
|
|
@ -3035,7 +3023,7 @@ unsigned char *DecompressData(const unsigned char *compData, int compDataSize, i
|
||||||
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
||||||
{
|
{
|
||||||
// Base64 conversion table from RFC 4648 [0..63]
|
// Base64 conversion table from RFC 4648 [0..63]
|
||||||
// NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sixtets" (6bit characters)
|
// NOTE: They represent 64 values (6 bits), to encode 3 bytes of data into 4 "sextets" (6bit characters)
|
||||||
static const char base64EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
static const char base64EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
// Compute expected size and padding
|
// Compute expected size and padding
|
||||||
|
|
@ -3122,7 +3110,7 @@ unsigned char *DecodeDataBase64(const char *text, int *outputSize)
|
||||||
int outputCount = 0;
|
int outputCount = 0;
|
||||||
for (int i = 0; i < dataSize;)
|
for (int i = 0; i < dataSize;)
|
||||||
{
|
{
|
||||||
// Every 4 sixtets must generate 3 octets
|
// Every 4 sextets must generate 3 octets
|
||||||
if ((i + 2) >= dataSize)
|
if ((i + 2) >= dataSize)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "BASE64: Decoding error: Input data size is not valid");
|
TRACELOG(LOG_WARNING, "BASE64: Decoding error: Input data size is not valid");
|
||||||
|
|
@ -3156,7 +3144,7 @@ unsigned char *DecodeDataBase64(const char *text, int *outputSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute CRC32 hash code
|
// Compute CRC32 hash code
|
||||||
unsigned int ComputeCRC32(unsigned char *data, int dataSize)
|
unsigned int ComputeCRC32(const 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,
|
||||||
|
|
@ -3202,7 +3190,7 @@ unsigned int ComputeCRC32(unsigned char *data, int dataSize)
|
||||||
|
|
||||||
// Compute MD5 hash code
|
// Compute MD5 hash code
|
||||||
// NOTE: Returns a static int[4] array (16 bytes)
|
// NOTE: Returns a static int[4] array (16 bytes)
|
||||||
unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
unsigned int *ComputeMD5(const unsigned char *data, int dataSize)
|
||||||
{
|
{
|
||||||
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||||
|
|
||||||
|
|
@ -3320,7 +3308,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
||||||
|
|
||||||
// Compute SHA-1 hash code
|
// Compute SHA-1 hash code
|
||||||
// NOTE: Returns a static int[5] array (20 bytes)
|
// NOTE: Returns a static int[5] array (20 bytes)
|
||||||
unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
|
unsigned int *ComputeSHA1(const unsigned char *data, int dataSize)
|
||||||
{
|
{
|
||||||
#define SHA1_ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
#define SHA1_ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||||
|
|
||||||
|
|
@ -3430,7 +3418,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
|
||||||
|
|
||||||
// Compute SHA-256 hash code
|
// Compute SHA-256 hash code
|
||||||
// NOTE: Returns a static int[8] array (32 bytes)
|
// NOTE: Returns a static int[8] array (32 bytes)
|
||||||
unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
|
unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||||
{
|
{
|
||||||
#define SHA256_ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int)*8) - c)))
|
#define SHA256_ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int)*8) - c)))
|
||||||
#define SHA256_A0(x) (SHA256_ROTATE_RIGHT(x, 7) ^ SHA256_ROTATE_RIGHT(x, 18) ^ (x >> 3))
|
#define SHA256_A0(x) (SHA256_ROTATE_RIGHT(x, 7) ^ SHA256_ROTATE_RIGHT(x, 18) ^ (x >> 3))
|
||||||
|
|
@ -3465,8 +3453,8 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
|
||||||
hash[6] = 0x1f83d9ab;
|
hash[6] = 0x1f83d9ab;
|
||||||
hash[7] = 0x5be0cd19;
|
hash[7] = 0x5be0cd19;
|
||||||
|
|
||||||
const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8;
|
const unsigned long long bitLen = 8ULL*dataSize;
|
||||||
unsigned long long int paddedSize = dataSize + sizeof(dataSize);
|
unsigned long long paddedSize = dataSize + sizeof(dataSize);
|
||||||
paddedSize += (64 - (paddedSize%64));
|
paddedSize += (64 - (paddedSize%64));
|
||||||
unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char));
|
unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char));
|
||||||
|
|
||||||
|
|
@ -3477,7 +3465,7 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
|
||||||
buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF;
|
buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++)
|
for (unsigned long long blockN = 0; blockN < paddedSize/64; blockN++)
|
||||||
{
|
{
|
||||||
unsigned int a = hash[0];
|
unsigned int a = hash[0];
|
||||||
unsigned int b = hash[1];
|
unsigned int b = hash[1];
|
||||||
|
|
@ -3499,7 +3487,7 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
|
||||||
}
|
}
|
||||||
for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16];
|
for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16];
|
||||||
|
|
||||||
for (unsigned long long int t = 0; t < 64; t++)
|
for (int t = 0; t < 64; t++)
|
||||||
{
|
{
|
||||||
unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25));
|
unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25));
|
||||||
unsigned int ch = ((e & f) ^ (~e & g));
|
unsigned int ch = ((e & f) ^ (~e & g));
|
||||||
|
|
@ -3630,7 +3618,7 @@ void UnloadAutomationEventList(AutomationEventList list)
|
||||||
// Export automation events list as text file
|
// Export automation events list as text file
|
||||||
bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#if SUPPORT_AUTOMATION_EVENTS
|
#if SUPPORT_AUTOMATION_EVENTS
|
||||||
// Export events as binary file
|
// Export events as binary file
|
||||||
|
|
@ -3648,7 +3636,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count);
|
memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count);
|
||||||
offset += sizeof(AutomationEvent)*list.count;
|
offset += sizeof(AutomationEvent)*list.count;
|
||||||
|
|
||||||
success = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
result = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
||||||
RL_FREE(binBuffer);
|
RL_FREE(binBuffer);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
@ -3679,12 +3667,12 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup automation event list to record to
|
// Setup automation event list to record to
|
||||||
|
|
@ -4121,8 +4109,8 @@ Vector2 GetMouseDelta(void)
|
||||||
{
|
{
|
||||||
Vector2 delta = { 0 };
|
Vector2 delta = { 0 };
|
||||||
|
|
||||||
delta.x = CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x;
|
delta.x = (CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x)*CORE.Input.Mouse.scale.x;
|
||||||
delta.y = CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y;
|
delta.y = (CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y)*CORE.Input.Mouse.scale.y;
|
||||||
|
|
||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
@ -4231,7 +4219,7 @@ void InitTimer(void)
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
||||||
{
|
{
|
||||||
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;
|
CORE.Time.base = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -4279,9 +4267,9 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
||||||
{
|
{
|
||||||
// Construct new path from our base path
|
// Construct new path from our base path
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name);
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, dp->d_name);
|
||||||
#else
|
#else
|
||||||
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name);
|
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, dp->d_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
|
||||||
|
|
@ -4293,7 +4281,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
||||||
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) ||
|
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) ||
|
||||||
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter))
|
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter))
|
||||||
{
|
{
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
memcpy(files->paths[files->count], path, pathLength);
|
||||||
files->count++;
|
files->count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4301,7 +4289,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
|
||||||
{
|
{
|
||||||
if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL)))
|
if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL)))
|
||||||
{
|
{
|
||||||
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1);
|
memcpy(files->paths[files->count], path, pathLength);
|
||||||
files->count++;
|
files->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,13 @@
|
||||||
// NOTE: Below types are required for standalone usage
|
// NOTE: Below types are required for standalone usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Boolean type
|
// Boolean type
|
||||||
|
#if !defined(__cplusplus)
|
||||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
|
#elif !defined(bool)
|
||||||
typedef enum bool { false = 0, true = !false } bool;
|
typedef enum bool { false = 0, true = !false } bool;
|
||||||
|
#define RL_BOOL_TYPE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(RL_VECTOR2_TYPE)
|
#if !defined(RL_VECTOR2_TYPE)
|
||||||
|
|
@ -124,7 +127,7 @@ void UpdateGestures(void); // Update gestures detec
|
||||||
|
|
||||||
#if defined(RGESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
bool IsGestureDetected(int gesture); // Check if a gesture has been detected
|
||||||
int GetGestureDetected(void); // Get latest detected gesture
|
int GetGestureDetected(void); // Get latest detected gesture
|
||||||
|
|
||||||
float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||||
|
|
@ -154,8 +157,8 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
// Functions required to query time on Windows
|
// Functions required to query time on Windows
|
||||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
int __stdcall QueryPerformanceCounter(unsigned long long *lpPerformanceCount);
|
||||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
int __stdcall QueryPerformanceFrequency(unsigned long long *lpFrequency);
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -297,10 +300,10 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_ACTION_UP)
|
else if (event.touchAction == TOUCH_ACTION_UP)
|
||||||
{
|
{
|
||||||
// A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases
|
// A swipe can happen while the current gesture is drag, but (especially for web) also hold, so set upPosition for both cases
|
||||||
if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0];
|
if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0];
|
||||||
|
|
||||||
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
|
// NOTE: GESTURES.Drag.intensity is dependent on the resolution of the screen
|
||||||
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.startTime));
|
GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.startTime));
|
||||||
|
|
||||||
|
|
@ -515,37 +518,36 @@ static double rgGetCurrentTime(void)
|
||||||
time = GetTime();
|
time = GetTime();
|
||||||
#else
|
#else
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned long long int clockFrequency, currentTime;
|
unsigned long long clockFrequency = 0;
|
||||||
|
unsigned long long currentClockTicks = 0;
|
||||||
|
|
||||||
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||||
QueryPerformanceCounter(¤tTime);
|
QueryPerformanceCounter(¤tClockTicks);
|
||||||
|
|
||||||
time = (double)currentTime/clockFrequency; // Time in seconds
|
time = (double)currentClockTicks/clockFrequency; // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// NOTE: Only for Linux-based systems
|
// NOTE: Only for Linux-based systems
|
||||||
struct timespec now;
|
struct timespec now = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||||
|
|
||||||
time = ((double)nowTime*1e-9); // Time in seconds
|
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
|
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
|
||||||
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
|
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
|
||||||
|
|
||||||
clock_serv_t cclock;
|
clock_serv_t cclock = { 0 };
|
||||||
mach_timespec_t now;
|
mach_timespec_t now = { 0 };
|
||||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||||
|
|
||||||
// NOTE: OS X does not have clock_gettime(), using clock_get_time()
|
// NOTE: OS X does not have clock_gettime(), using clock_get_time()
|
||||||
clock_get_time(cclock, &now);
|
clock_get_time(cclock, &now);
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||||
|
|
||||||
time = ((double)nowTime*1e-9); // Time in seconds
|
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
61
src/rlgl.h
61
src/rlgl.h
|
|
@ -7,10 +7,10 @@
|
||||||
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
||||||
*
|
*
|
||||||
* ADDITIONAL NOTES:
|
* ADDITIONAL NOTES:
|
||||||
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
|
* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffers are
|
||||||
* initialized on rlglInit() to accumulate vertex data
|
* initialized on rlglInit() to accumulate vertex data
|
||||||
*
|
*
|
||||||
* When an internal state change is required all the stored vertex data is rendered in batch,
|
* When an internal state change is required all the stored vertex data is rendered in a batch,
|
||||||
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch
|
* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch
|
||||||
*
|
*
|
||||||
* Some resources are also loaded for convenience, here the complete list:
|
* Some resources are also loaded for convenience, here the complete list:
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
* #define GRAPHICS_API_OPENGL_ES2
|
* #define GRAPHICS_API_OPENGL_ES2
|
||||||
* #define GRAPHICS_API_OPENGL_ES3
|
* #define GRAPHICS_API_OPENGL_ES3
|
||||||
* Use selected OpenGL graphics backend, should be supported by platform
|
* Use selected OpenGL graphics backend, should be supported by platform
|
||||||
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
* Those preprocessor defines are only used on the rlgl module, if OpenGL version is
|
||||||
* required by any other module, use rlGetVersion() to check it
|
* required by any other module, use rlGetVersion() to check it
|
||||||
*
|
*
|
||||||
* #define RLGL_IMPLEMENTATION
|
* #define RLGL_IMPLEMENTATION
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
|
* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
|
||||||
* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
|
* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
|
||||||
* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
|
* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
|
||||||
* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
|
* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of texture units that can be activated on batch drawing (SetShaderValueTexture())
|
||||||
*
|
*
|
||||||
* #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
|
||||||
|
|
@ -359,11 +359,13 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
#if !defined(__cplusplus)
|
||||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
|
#elif !defined(bool)
|
||||||
// Boolean type
|
|
||||||
typedef enum bool { false = 0, true = !false } bool;
|
typedef enum bool { false = 0, true = !false } bool;
|
||||||
|
#define RL_BOOL_TYPE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(RL_MATRIX_TYPE)
|
#if !defined(RL_MATRIX_TYPE)
|
||||||
|
|
@ -881,7 +883,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms,
|
// NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms,
|
||||||
// in that case, functions are loaded from a custom glad for OpenGL ES 2.0
|
// in that case, functions are loaded from a custom glad for OpenGL ES 2.0
|
||||||
// TODO: OpenGL ES 2.0 support shouldn't be platform-dependant, neither require GLAD
|
// TODO: OpenGL ES 2.0 support shouldn't be platform-dependent, neither require GLAD
|
||||||
#if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
|
#if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
|
||||||
#define GLAD_GLES2_IMPLEMENTATION
|
#define GLAD_GLES2_IMPLEMENTATION
|
||||||
#include "external/glad_gles2.h"
|
#include "external/glad_gles2.h"
|
||||||
|
|
@ -894,7 +896,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
|
|
||||||
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
|
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
|
||||||
// provided headers (despite being defined in official Khronos GLES2 headers)
|
// provided headers (despite being defined in official Khronos GLES2 headers)
|
||||||
// TODO: Avoid raylib platform-dependant code on rlgl, it should be a completely portable library
|
// TODO: Avoid raylib platform-dependent code on rlgl, it should be a completely portable library
|
||||||
#if defined(PLATFORM_DRM)
|
#if defined(PLATFORM_DRM)
|
||||||
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
|
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
|
||||||
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
|
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
|
||||||
|
|
@ -1016,9 +1018,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
|
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
|
||||||
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
|
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
|
||||||
#endif
|
#endif
|
||||||
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES
|
|
||||||
#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEMATRICES
|
|
||||||
#endif
|
|
||||||
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM
|
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM
|
||||||
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM
|
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1142,21 +1142,23 @@ typedef struct rlglData {
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
static bool isGpuReady = false;
|
||||||
static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR;
|
static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR;
|
||||||
static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
|
static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
static rlglData RLGL = { 0 };
|
static rlglData RLGL = { 0 };
|
||||||
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
|
#endif
|
||||||
static bool isGpuReady = false;
|
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
|
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
|
||||||
|
// VAO functions entry points
|
||||||
// NOTE: VAO functionality is exposed through extensions (OES)
|
// NOTE: VAO functionality is exposed through extensions (OES)
|
||||||
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
|
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
|
||||||
static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
|
static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
|
||||||
static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
|
static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
|
||||||
|
|
||||||
// NOTE: Instancing functionality could also be available through extension
|
// Instancing functionality entry points
|
||||||
|
// NOTE: Instancing functionality could be available through extensions
|
||||||
static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL;
|
static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL;
|
||||||
static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL;
|
static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL;
|
||||||
static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
|
static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
|
||||||
|
|
@ -1393,7 +1395,7 @@ void rlFrustum(double left, double right, double bottom, double top, double znea
|
||||||
void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
|
void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
|
||||||
{
|
{
|
||||||
// NOTE: If left-right and top-botton values are equal it could create a division by zero,
|
// NOTE: If left-right and top-botton values are equal it could create a division by zero,
|
||||||
// response to it is platform/compiler dependant
|
// response to it is platform/compiler dependent
|
||||||
Matrix matOrtho = { 0 };
|
Matrix matOrtho = { 0 };
|
||||||
|
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
|
|
@ -1512,7 +1514,7 @@ void rlBegin(int mode)
|
||||||
// Finish vertex providing
|
// Finish vertex providing
|
||||||
void rlEnd(void)
|
void rlEnd(void)
|
||||||
{
|
{
|
||||||
// NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
|
// NOTE: Depth increment is dependent on rlOrtho(): z-near and z-far values,
|
||||||
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
|
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
|
||||||
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
|
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
|
||||||
RLGL.currentBatch->currentDepth += (1.0f/20000.0f);
|
RLGL.currentBatch->currentDepth += (1.0f/20000.0f);
|
||||||
|
|
@ -1624,6 +1626,11 @@ void rlNormal3f(float x, float y, float z)
|
||||||
normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
|
normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
|
||||||
normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
|
normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Default behavior assumes the normal vector is in the correct space for what the shader expects,
|
||||||
|
// it could be not normalized to 0.0f..1.0f, magnitud can be useed for some effects
|
||||||
|
/*
|
||||||
|
// WARNING: Vector normalization if required
|
||||||
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
|
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
|
||||||
if (length != 0.0f)
|
if (length != 0.0f)
|
||||||
{
|
{
|
||||||
|
|
@ -1632,6 +1639,7 @@ void rlNormal3f(float x, float y, float z)
|
||||||
normaly *= ilength;
|
normaly *= ilength;
|
||||||
normalz *= ilength;
|
normalz *= ilength;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
RLGL.State.normalx = normalx;
|
RLGL.State.normalx = normalx;
|
||||||
RLGL.State.normaly = normaly;
|
RLGL.State.normaly = normaly;
|
||||||
RLGL.State.normalz = normalz;
|
RLGL.State.normalz = normalz;
|
||||||
|
|
@ -1914,7 +1922,7 @@ void rlBindFramebuffer(unsigned int target, unsigned int framebuffer)
|
||||||
void rlActiveDrawBuffers(int count)
|
void rlActiveDrawBuffers(int count)
|
||||||
{
|
{
|
||||||
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3))
|
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3))
|
||||||
// NOTE: Maximum number of draw buffers supported is implementation dependant,
|
// NOTE: Maximum number of draw buffers supported is implementation dependent,
|
||||||
// it can be queried with glGet*() but it must be at least 8
|
// it can be queried with glGet*() but it must be at least 8
|
||||||
//GLint maxDrawBuffers = 0;
|
//GLint maxDrawBuffers = 0;
|
||||||
//glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
//glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||||
|
|
@ -3372,8 +3380,15 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
||||||
// Texture parameters configuration
|
// Texture parameters configuration
|
||||||
// NOTE: glTexParameteri does NOT affect texture uploading
|
// NOTE: glTexParameteri does NOT affect texture uploading
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
||||||
|
// Check if texture is power-of-two (POT)
|
||||||
|
bool texIsPOT = false;
|
||||||
|
|
||||||
|
if (((width > 0) && ((width & (width - 1)) == 0)) &&
|
||||||
|
((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
|
||||||
|
|
||||||
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
|
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
|
||||||
if (RLGL.ExtSupported.texNPOT)
|
if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
|
||||||
{
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
|
||||||
|
|
@ -3644,7 +3659,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
||||||
#else // defined(GRAPHICS_API_OPENGL_ES2)
|
#else // GRAPHICS_API_OPENGL_ES2
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||||
|
|
@ -3693,6 +3708,8 @@ void rlUnloadTexture(unsigned int id)
|
||||||
// NOTE: Only supports GPU mipmap generation
|
// NOTE: Only supports GPU mipmap generation
|
||||||
void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
|
void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
|
||||||
{
|
{
|
||||||
|
if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return; }
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
|
||||||
|
|
@ -4659,14 +4676,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
|
||||||
// Get SSBO buffer size
|
// Get SSBO buffer size
|
||||||
unsigned int rlGetShaderBufferSize(unsigned int id)
|
unsigned int rlGetShaderBufferSize(unsigned int id)
|
||||||
{
|
{
|
||||||
|
unsigned int result = 0;
|
||||||
#if defined(GRAPHICS_API_OPENGL_43)
|
#if defined(GRAPHICS_API_OPENGL_43)
|
||||||
GLint64 size = 0;
|
GLint64 size = 0;
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
||||||
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
|
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
|
||||||
return (size > 0)? (unsigned int)size : 0;
|
if (size > 0) result = (unsigned int)size;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read SSBO buffer data (GPU->CPU)
|
// Read SSBO buffer data (GPU->CPU)
|
||||||
|
|
|
||||||
119
src/rmodels.c
119
src/rmodels.c
|
|
@ -3,18 +3,19 @@
|
||||||
* rmodels - Basic functions to draw 3d shapes and load and draw 3d models
|
* rmodels - Basic functions to draw 3d shapes and load and draw 3d models
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_MODULE_RMODELS
|
* #define SUPPORT_MODULE_RMODELS 1
|
||||||
* rmodels module is included in the build
|
* rmodels module is included in the build
|
||||||
*
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_OBJ
|
* #define SUPPORT_FILEFORMAT_OBJ 1
|
||||||
* #define SUPPORT_FILEFORMAT_MTL
|
* #define SUPPORT_FILEFORMAT_MTL 1
|
||||||
* #define SUPPORT_FILEFORMAT_IQM
|
* #define SUPPORT_FILEFORMAT_IQM 1
|
||||||
* #define SUPPORT_FILEFORMAT_GLTF
|
* #define SUPPORT_FILEFORMAT_GLTF 1
|
||||||
* #define SUPPORT_FILEFORMAT_VOX
|
* #define SUPPORT_FILEFORMAT_GLTF_WRITE 0
|
||||||
* #define SUPPORT_FILEFORMAT_M3D
|
* #define SUPPORT_FILEFORMAT_VOX 1
|
||||||
|
* #define SUPPORT_FILEFORMAT_M3D 1
|
||||||
* Selected desired fileformats to be supported for model data loading
|
* Selected desired fileformats to be supported for model data loading
|
||||||
*
|
*
|
||||||
* #define SUPPORT_MESH_GENERATION
|
* #define SUPPORT_MESH_GENERATION 1
|
||||||
* Support procedural mesh generation functions, uses external par_shapes.h library
|
* Support procedural mesh generation functions, uses external par_shapes.h library
|
||||||
* NOTE: Some generated meshes DO NOT include generated texture coordinates
|
* NOTE: Some generated meshes DO NOT include generated texture coordinates
|
||||||
*
|
*
|
||||||
|
|
@ -71,6 +72,11 @@
|
||||||
#define CGLTF_IMPLEMENTATION
|
#define CGLTF_IMPLEMENTATION
|
||||||
#include "external/cgltf.h" // glTF file format loading
|
#include "external/cgltf.h" // glTF file format loading
|
||||||
#endif
|
#endif
|
||||||
|
#if SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||||
|
// NOTE: No need for custom allocators, memory buffer provided
|
||||||
|
#define CGLTF_WRITE_IMPLEMENTATION
|
||||||
|
#include "external/cgltf_write.h" // glTF file format writing
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_VOX
|
#if SUPPORT_FILEFORMAT_VOX
|
||||||
#define VOX_MALLOC RL_MALLOC
|
#define VOX_MALLOC RL_MALLOC
|
||||||
|
|
@ -79,7 +85,7 @@
|
||||||
#define VOX_FREE RL_FREE
|
#define VOX_FREE RL_FREE
|
||||||
|
|
||||||
#define VOX_LOADER_IMPLEMENTATION
|
#define VOX_LOADER_IMPLEMENTATION
|
||||||
#include "external/vox_loader.h" // VOX file format loading (MagikaVoxel)
|
#include "external/vox_loader.h" // VOX file format loading (MagicaVoxel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_M3D
|
#if SUPPORT_FILEFORMAT_M3D
|
||||||
|
|
@ -713,9 +719,9 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
|
||||||
|
|
||||||
// Draw a wired cylinder with base at startPos and top at endPos
|
// Draw a wired cylinder with base at startPos and top at endPos
|
||||||
// NOTE: It could be also used for pyramid and cone
|
// NOTE: It could be also used for pyramid and cone
|
||||||
void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)
|
void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int slices, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (slices < 3) slices = 3;
|
||||||
|
|
||||||
Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
|
Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
|
||||||
if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check
|
if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check
|
||||||
|
|
@ -724,12 +730,12 @@ void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, fl
|
||||||
Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
|
Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));
|
||||||
Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
|
Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));
|
||||||
|
|
||||||
float baseAngle = (2.0f*PI)/sides;
|
float baseAngle = (2.0f*PI)/slices;
|
||||||
|
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < slices; i++)
|
||||||
{
|
{
|
||||||
// Compute the four vertices
|
// Compute the four vertices
|
||||||
float s1 = sinf(baseAngle*(i + 0))*startRadius;
|
float s1 = sinf(baseAngle*(i + 0))*startRadius;
|
||||||
|
|
@ -758,7 +764,7 @@ void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a capsule with the center of its sphere caps at startPos and endPos
|
// Draw a capsule with the center of its sphere caps at startPos and endPos
|
||||||
void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
|
void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color)
|
||||||
{
|
{
|
||||||
if (slices < 3) slices = 3;
|
if (slices < 3) slices = 3;
|
||||||
|
|
||||||
|
|
@ -897,7 +903,7 @@ void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw capsule wires with the center of its sphere caps at startPos and endPos
|
// Draw capsule wires with the center of its sphere caps at startPos and endPos
|
||||||
void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)
|
void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color)
|
||||||
{
|
{
|
||||||
if (slices < 3) slices = 3;
|
if (slices < 3) slices = 3;
|
||||||
|
|
||||||
|
|
@ -1178,9 +1184,10 @@ bool IsModelValid(Model model)
|
||||||
if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU
|
if ((model.meshes[i].tangents != NULL) && (model.meshes[i].vboId[4] == 0)) { result = false; break; } // Vertex tangents buffer not uploaded to GPU
|
||||||
if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU
|
if ((model.meshes[i].texcoords2 != NULL) && (model.meshes[i].vboId[5] == 0)) { result = false; break; } // Vertex texcoords2 buffer not uploaded to GPU
|
||||||
if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU
|
if ((model.meshes[i].indices != NULL) && (model.meshes[i].vboId[6] == 0)) { result = false; break; } // Vertex indices buffer not uploaded to GPU
|
||||||
|
#if SUPPORT_GPU_SKINNING
|
||||||
if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU
|
if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU
|
||||||
if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
|
if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
|
||||||
|
#endif
|
||||||
// NOTE: Some OpenGL versions do not support VAO, so avoid below check
|
// NOTE: Some OpenGL versions do not support VAO, so avoid below check
|
||||||
//if (model.meshes[i].vaoId == 0) { result = false; break }
|
//if (model.meshes[i].vaoId == 0) { result = false; break }
|
||||||
}
|
}
|
||||||
|
|
@ -1276,7 +1283,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
mesh->vaoId = rlLoadVertexArray();
|
mesh->vaoId = rlLoadVertexArray();
|
||||||
if (mesh->vaoId == 0) return;
|
|
||||||
|
|
||||||
rlEnableVertexArray(mesh->vaoId);
|
rlEnableVertexArray(mesh->vaoId);
|
||||||
|
|
||||||
|
|
@ -1945,7 +1951,7 @@ void UnloadMesh(Mesh mesh)
|
||||||
// Export mesh data to file
|
// Export mesh data to file
|
||||||
bool ExportMesh(Mesh mesh, const char *fileName)
|
bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
if (IsFileExtension(fileName, ".obj"))
|
if (IsFileExtension(fileName, ".obj"))
|
||||||
{
|
{
|
||||||
|
|
@ -2009,22 +2015,35 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
}
|
}
|
||||||
|
else if (IsFileExtension(fileName, ".gltf")) // Or .glb
|
||||||
|
{
|
||||||
|
// TODO: Implement gltf/glb support
|
||||||
|
/*
|
||||||
|
cgltf_size expected = cgltf_write(options, NULL, 0, data);
|
||||||
|
char *buffer = (char *)RL_CALLOC(expected, 0);
|
||||||
|
cgltf_size actual = cgltf_write(options, buffer, expected, data);
|
||||||
|
|
||||||
|
// NOTE: cgltf_write() includes a NULL terminator that should be ommited in case of a .glb
|
||||||
|
if (options->type == cgltf_file_type_glb) cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
|
||||||
|
else SaveFileText(fileName, buffer); // Write a plain JSON file
|
||||||
|
*/
|
||||||
|
}
|
||||||
else if (IsFileExtension(fileName, ".raw"))
|
else if (IsFileExtension(fileName, ".raw"))
|
||||||
{
|
{
|
||||||
// TODO: Support additional file formats to export mesh vertex data
|
// TODO: Support additional file formats to export mesh vertex data
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
|
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
|
||||||
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -2108,14 +2127,14 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
//if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
//if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||||
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
||||||
|
|
@ -3912,7 +3931,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
|
||||||
Color colDiffuse = mat.maps[MATERIAL_MAP_DIFFUSE].color;
|
Color colDiffuse = mat.maps[MATERIAL_MAP_DIFFUSE].color;
|
||||||
|
|
||||||
// Applying color tint directly to material diffuse map,
|
// Applying color tint directly to material diffuse map,
|
||||||
// because is comes as an input paramter to the function
|
// because it comes as an input parameter to the function
|
||||||
Color colTinted = { 0 };
|
Color colTinted = { 0 };
|
||||||
colTinted.r = (unsigned char)(((int)colDiffuse.r*(int)tint.r)/255);
|
colTinted.r = (unsigned char)(((int)colDiffuse.r*(int)tint.r)/255);
|
||||||
colTinted.g = (unsigned char)(((int)colDiffuse.g*(int)tint.g)/255);
|
colTinted.g = (unsigned char)(((int)colDiffuse.g*(int)tint.g)/255);
|
||||||
|
|
@ -3956,32 +3975,6 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
|
||||||
rlDisableWireMode();
|
rlDisableWireMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a model points
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
|
||||||
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
|
||||||
{
|
|
||||||
rlEnablePointMode();
|
|
||||||
rlDisableBackfaceCulling();
|
|
||||||
|
|
||||||
DrawModel(model, position, scale, tint);
|
|
||||||
|
|
||||||
rlEnableBackfaceCulling();
|
|
||||||
rlDisablePointMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a model points
|
|
||||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
|
||||||
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
|
||||||
{
|
|
||||||
rlEnablePointMode();
|
|
||||||
rlDisableBackfaceCulling();
|
|
||||||
|
|
||||||
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
|
||||||
|
|
||||||
rlEnableBackfaceCulling();
|
|
||||||
rlDisablePointMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a billboard
|
// Draw a billboard
|
||||||
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
|
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
|
||||||
{
|
{
|
||||||
|
|
@ -4107,7 +4100,8 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Check for distances squared to avoid sqrtf()
|
// Check for distances squared to avoid sqrtf()
|
||||||
if (Vector3DotProduct(Vector3Subtract(center2, center1), Vector3Subtract(center2, center1)) <= (radius1 + radius2)*(radius1 + radius2)) collision = true;
|
float radSum = radius1 + radius2;
|
||||||
|
if (Vector3DistanceSqr(center1, center2) <= (radSum*radSum)) collision = true;
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
@ -4133,18 +4127,13 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)
|
||||||
{
|
{
|
||||||
bool collision = false;
|
bool collision = false;
|
||||||
|
|
||||||
float dmin = 0;
|
Vector3 closestPoint = {
|
||||||
|
Clamp(center.x, box.min.x, box.max.x),
|
||||||
|
Clamp(center.y, box.min.y, box.max.y),
|
||||||
|
Clamp(center.z, box.min.z, box.max.z)
|
||||||
|
};
|
||||||
|
|
||||||
if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2);
|
if (Vector3DistanceSqr(center, closestPoint) <= (radius*radius)) collision = true;
|
||||||
else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);
|
|
||||||
|
|
||||||
if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);
|
|
||||||
else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);
|
|
||||||
|
|
||||||
if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);
|
|
||||||
else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);
|
|
||||||
|
|
||||||
if (dmin <= (radius*radius)) collision = true;
|
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
@ -5286,7 +5275,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release file data callback for cgltf
|
// Release file data callback for cgltf
|
||||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)
|
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data, cgltf_size size)
|
||||||
{
|
{
|
||||||
UnloadFileData((unsigned char *)data);
|
UnloadFileData((unsigned char *)data);
|
||||||
}
|
}
|
||||||
|
|
@ -6900,7 +6889,7 @@ static Model LoadM3D(const char *fileName)
|
||||||
mi = m3d->face[i].materialid;
|
mi = m3d->face[i].materialid;
|
||||||
|
|
||||||
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
|
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
|
||||||
// if all colors are fully transparent black for all verteces of this materal, then assuming no vertex colors
|
// if all colors are fully transparent black for all vertices of this material, then assuming no vertex colors
|
||||||
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
|
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
|
||||||
{
|
{
|
||||||
if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
|
if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,18 @@
|
||||||
* are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
|
* are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
|
||||||
*
|
*
|
||||||
* Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a
|
* Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a
|
||||||
* user-provided texture with SetShapesTexture(), the pourpouse of this implementation
|
* user-provided texture with SetShapesTexture(), the purpose of this implementation
|
||||||
* is allowing to reduce draw calls when combined with a texture-atlas
|
* is allowing to reduce draw calls when combined with a texture-atlas
|
||||||
*
|
*
|
||||||
* By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one
|
* By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one
|
||||||
* white character of default font [rtext], this way, raylib text and shapes can be draw with
|
* white character of default font [rtext], this way, raylib text and shapes can be drawn with
|
||||||
* a single draw call and it also allows users to configure it the same way with their own fonts
|
* a single draw call and it also allows users to configure it the same way with their own fonts
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_MODULE_RSHAPES
|
* #define SUPPORT_MODULE_RSHAPES 1
|
||||||
* rshapes module is included in the build
|
* rshapes module is included in the build
|
||||||
*
|
*
|
||||||
* #define SUPPORT_QUADS_DRAW_MODE
|
* #define SUPPORT_QUADS_DRAW_MODE 1
|
||||||
* Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES
|
* Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
@ -289,6 +289,22 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
DrawCircleSector(center, radius, 0, 360, 36, color);
|
DrawCircleSector(center, radius, 0, 360, 36, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a gradient-filled circle
|
||||||
|
void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
for (int i = 0; i < 360; i += 10)
|
||||||
|
{
|
||||||
|
rlColor4ub(inner.r, inner.g, inner.b, inner.a);
|
||||||
|
rlVertex2f(center.x, center.y);
|
||||||
|
rlColor4ub(outer.r, outer.g, outer.b, outer.a);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radius, center.y + sinf(DEG2RAD*(i + 10))*radius);
|
||||||
|
rlColor4ub(outer.r, outer.g, outer.b, outer.a);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*i)*radius, center.y + sinf(DEG2RAD*i)*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a piece of a circle
|
// Draw a piece of a circle
|
||||||
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
|
||||||
{
|
{
|
||||||
|
|
@ -438,22 +454,6 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a gradient-filled circle
|
|
||||||
void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
|
|
||||||
{
|
|
||||||
rlBegin(RL_TRIANGLES);
|
|
||||||
for (int i = 0; i < 360; i += 10)
|
|
||||||
{
|
|
||||||
rlColor4ub(inner.r, inner.g, inner.b, inner.a);
|
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
|
||||||
rlColor4ub(outer.r, outer.g, outer.b, outer.a);
|
|
||||||
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
|
|
||||||
rlColor4ub(outer.r, outer.g, outer.b, outer.a);
|
|
||||||
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
|
|
||||||
}
|
|
||||||
rlEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw circle outline
|
// Draw circle outline
|
||||||
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
{
|
{
|
||||||
|
|
@ -1386,6 +1386,12 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
|
||||||
// Draw a triangle
|
// Draw a triangle
|
||||||
// NOTE: Vertex must be provided in counter-clockwise order
|
// NOTE: Vertex must be provided in counter-clockwise order
|
||||||
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
|
{
|
||||||
|
DrawTriangleGradient(v1, v2, v3, color, color, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw triangle with interpolated colors (vertex in counter-clockwise order!)
|
||||||
|
void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
|
||||||
{
|
{
|
||||||
#if SUPPORT_QUADS_DRAW_MODE
|
#if SUPPORT_QUADS_DRAW_MODE
|
||||||
rlSetTexture(GetShapesTexture().id);
|
rlSetTexture(GetShapesTexture().id);
|
||||||
|
|
@ -1393,17 +1399,20 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
|
rlColor4ub(c1.r, c1.g, c1.b, c1.a);
|
||||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||||
rlVertex2f(v1.x, v1.y);
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
|
||||||
|
rlColor4ub(c2.r, c2.g, c2.b, c2.a);
|
||||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||||
rlVertex2f(v2.x, v2.y);
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
|
||||||
|
rlColor4ub(c3.r, c3.g, c3.b, c3.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(v3.x, v3.y);
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
|
||||||
|
rlColor4ub(c3.r, c3.g, c3.b, c3.a);
|
||||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||||
rlVertex2f(v3.x, v3.y);
|
rlVertex2f(v3.x, v3.y);
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
@ -1411,9 +1420,11 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
#else
|
#else
|
||||||
rlBegin(RL_TRIANGLES);
|
rlBegin(RL_TRIANGLES);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(c1.r, c1.g, c1.b, c1.a);
|
||||||
rlVertex2f(v1.x, v1.y);
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlColor4ub(c2.r, c2.g, c2.b, c2.a);
|
||||||
rlVertex2f(v2.x, v2.y);
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlColor4ub(c3.r, c3.g, c3.b, c3.a);
|
||||||
rlVertex2f(v3.x, v3.y);
|
rlVertex2f(v3.x, v3.y);
|
||||||
rlEnd();
|
rlEnd();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1496,7 +1507,7 @@ void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a regular polygon of n sides (Vector version)
|
// Draw a polygon of n sides
|
||||||
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
|
|
@ -2179,7 +2190,7 @@ Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get spline point for a given t [0.0f .. 1.0f], Quadratic Bezier
|
// Get spline point for a given t [0.0f .. 1.0f], Quadratic Bezier
|
||||||
Vector2 GetSplinePointBezierQuad(Vector2 startPos, Vector2 controlPos, Vector2 endPos, float t)
|
Vector2 GetSplinePointBezierQuadratic(Vector2 startPos, Vector2 controlPos, Vector2 endPos, float t)
|
||||||
{
|
{
|
||||||
Vector2 point = { 0 };
|
Vector2 point = { 0 };
|
||||||
|
|
||||||
|
|
@ -2313,16 +2324,18 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||||
float dx = fabsf(center.x - recCenterX);
|
float dx = fabsf(center.x - recCenterX);
|
||||||
float dy = fabsf(center.y - recCenterY);
|
float dy = fabsf(center.y - recCenterY);
|
||||||
|
|
||||||
if (dx > (rec.width/2.0f + radius)) { return false; }
|
if ((dx <= (rec.width/2.0f + radius)) && (dy <= (rec.height/2.0f + radius)))
|
||||||
if (dy > (rec.height/2.0f + radius)) { return false; }
|
{
|
||||||
|
if (dx <= (rec.width/2.0f)) collision = true;
|
||||||
if (dx <= (rec.width/2.0f)) { return true; }
|
else if (dy <= (rec.height/2.0f)) collision = true;
|
||||||
if (dy <= (rec.height/2.0f)) { return true; }
|
else
|
||||||
|
{
|
||||||
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
||||||
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
||||||
|
|
||||||
collision = (cornerDistanceSq <= (radius*radius));
|
collision = (cornerDistanceSq <= (radius*radius));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
@ -2349,9 +2362,12 @@ bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2,
|
||||||
float u = (s12x*ry - s12y*rx)/div;
|
float u = (s12x*ry - s12y*rx)/div;
|
||||||
|
|
||||||
if ((0.0f <= t) && (t <= 1.0f) && (0.0f <= u) && (u <= 1.0f))
|
if ((0.0f <= t) && (t <= 1.0f) && (0.0f <= u) && (u <= 1.0f))
|
||||||
|
{
|
||||||
|
if (collisionPoint)
|
||||||
{
|
{
|
||||||
collisionPoint->x = startPos1.x + t*rx;
|
collisionPoint->x = startPos1.x + t*rx;
|
||||||
collisionPoint->y = startPos1.y + t*ry;
|
collisionPoint->y = startPos1.y + t*ry;
|
||||||
|
}
|
||||||
|
|
||||||
collision = true;
|
collision = true;
|
||||||
}
|
}
|
||||||
|
|
@ -2383,14 +2399,17 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
|
||||||
// Check if circle collides with a line created between two points [p1] and [p2]
|
// Check if circle collides with a line created between two points [p1] and [p2]
|
||||||
bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
||||||
{
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
float dx = p1.x - p2.x;
|
float dx = p1.x - p2.x;
|
||||||
float dy = p1.y - p2.y;
|
float dy = p1.y - p2.y;
|
||||||
|
|
||||||
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
|
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
|
||||||
{
|
{
|
||||||
return CheckCollisionCircles(p1, 0, center, radius);
|
collision = CheckCollisionCircles(p1, 0, center, radius);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
float lengthSQ = ((dx*dx) + (dy*dy));
|
float lengthSQ = ((dx*dx) + (dy*dy));
|
||||||
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
|
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
|
||||||
|
|
||||||
|
|
@ -2401,7 +2420,10 @@ bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2
|
||||||
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
|
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
|
||||||
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
|
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
|
||||||
|
|
||||||
return (distanceSQ <= radius*radius);
|
if (distanceSQ <= radius*radius) collision = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get collision rectangle for two rectangles collision
|
// Get collision rectangle for two rectangles collision
|
||||||
|
|
|
||||||
182
src/rtext.c
182
src/rtext.c
|
|
@ -3,22 +3,22 @@
|
||||||
* rtext - Basic functions to load fonts and draw text
|
* rtext - Basic functions to load fonts and draw text
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_MODULE_RTEXT
|
* #define SUPPORT_MODULE_RTEXT 1
|
||||||
* rtext module is included in the build
|
* rtext module is included in the build
|
||||||
*
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_FNT
|
* #define SUPPORT_FILEFORMAT_FNT 1
|
||||||
* #define SUPPORT_FILEFORMAT_TTF
|
* #define SUPPORT_FILEFORMAT_TTF 1
|
||||||
* #define SUPPORT_FILEFORMAT_BDF
|
* #define SUPPORT_FILEFORMAT_BDF 0
|
||||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||||
* supported by default, to remove support, comment unrequired #define in this module
|
* supported by default, to remove support, #define as 0 in this module or your build system
|
||||||
*
|
*
|
||||||
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
|
* #define MAX_TEXT_BUFFER_LENGTH 1024
|
||||||
* TextSplit() function static buffer max size
|
* Text functions using static buffer max size
|
||||||
*
|
*
|
||||||
* #define MAX_TEXTSPLIT_COUNT
|
* #define MAX_TEXTSPLIT_COUNT 128
|
||||||
* TextSplit() function static substrings pointers array (pointing to static buffer)
|
* TextSplit() function static substrings pointers array (pointing to static buffer)
|
||||||
*
|
*
|
||||||
* #define FONT_ATLAS_CORNER_REC_SIZE
|
* #define FONT_ATLAS_CORNER_REC_SIZE 3
|
||||||
* On font atlas image generation [GenImageFontAtlas()], add a NxN pixels white rectangle
|
* On font atlas image generation [GenImageFontAtlas()], add a NxN pixels white rectangle
|
||||||
* at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
* at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
||||||
* drawing text and shapes with a single draw call [SetShapesTexture()]
|
* drawing text and shapes with a single draw call [SetShapesTexture()]
|
||||||
|
|
@ -156,7 +156,7 @@ extern void LoadFontDefault(void)
|
||||||
{
|
{
|
||||||
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
||||||
|
|
||||||
// Check to see if the font for an image has alreeady been allocated,
|
// Check to see if the font for an image has already been allocated,
|
||||||
// and if no need to upload, then return
|
// and if no need to upload, then return
|
||||||
if (defaultFont.glyphs != NULL) return;
|
if (defaultFont.glyphs != NULL) return;
|
||||||
|
|
||||||
|
|
@ -1017,7 +1017,7 @@ void UnloadFont(Font font)
|
||||||
// Export font as code file, returns true on success
|
// Export font as code file, returns true on success
|
||||||
bool ExportFontAsCode(Font font, const char *fileName)
|
bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -1159,14 +1159,14 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw current FPS
|
// Draw current FPS
|
||||||
|
|
@ -1279,7 +1279,7 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
||||||
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw multiple character (codepoints)
|
// Draw multiple characters (codepoints)
|
||||||
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
|
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
float textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
float textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||||
|
|
@ -1395,8 +1395,7 @@ Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, floa
|
||||||
{
|
{
|
||||||
Vector2 textSize = { 0 };
|
Vector2 textSize = { 0 };
|
||||||
|
|
||||||
// Security check
|
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize; // Security check
|
||||||
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize;
|
|
||||||
|
|
||||||
float textWidth = 0.0f;
|
float textWidth = 0.0f;
|
||||||
// Used to count longer text line width
|
// Used to count longer text line width
|
||||||
|
|
@ -1675,7 +1674,7 @@ int TextCopy(char *dst, const char *src)
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if two text string are equal
|
// Check if two text strings are equal
|
||||||
// REQUIRES: strcmp()
|
// REQUIRES: strcmp()
|
||||||
bool TextIsEqual(const char *text1, const char *text2)
|
bool TextIsEqual(const char *text1, const char *text2)
|
||||||
{
|
{
|
||||||
|
|
@ -1699,8 +1698,8 @@ const char *TextSubtext(const char *text, int position, int length)
|
||||||
{
|
{
|
||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
||||||
if (position >= textLength) return buffer; // First char is already '\0' by memset
|
if (position < textLength)
|
||||||
|
{
|
||||||
int maxLength = textLength - position;
|
int maxLength = textLength - position;
|
||||||
if (length > maxLength) length = maxLength;
|
if (length > maxLength) length = maxLength;
|
||||||
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
||||||
|
|
@ -1711,6 +1710,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
||||||
|
|
||||||
buffer[length] = '\0';
|
buffer[length] = '\0';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -1724,7 +1724,7 @@ const char *TextRemoveSpaces(const char *text)
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
// Avoid copying the ' ' characters
|
// Avoid copying the ' ' characters
|
||||||
for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++)
|
for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++)
|
||||||
{
|
{
|
||||||
if (text[i] != ' ') { buffer[j] = text[i]; j++; }
|
if (text[i] != ' ') { buffer[j] = text[i]; j++; }
|
||||||
}
|
}
|
||||||
|
|
@ -1736,8 +1736,6 @@ const char *TextRemoveSpaces(const char *text)
|
||||||
// Get text between two strings
|
// Get text between two strings
|
||||||
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
{
|
{
|
||||||
#define MAX_TEXT_BETWEEN_SIZE 1024
|
|
||||||
|
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
|
@ -1752,8 +1750,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
{
|
{
|
||||||
endIndex += (beginIndex + beginLen);
|
endIndex += (beginIndex + beginLen);
|
||||||
int len = (endIndex - beginIndex - beginLen);
|
int len = (endIndex - beginIndex - beginLen);
|
||||||
if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1);
|
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1762,8 +1760,74 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||||
|
|
||||||
// Replace text string
|
// Replace text string
|
||||||
// REQUIRES: strstr(), strncpy()
|
// REQUIRES: strstr(), strncpy()
|
||||||
// WARNING: Allocated memory must be manually freed
|
// NOTE: Limited text replace functionality, using static string
|
||||||
char *TextReplace(const char *text, const char *search, const char *replacement)
|
char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (search != NULL) && (search[0] != '\0'))
|
||||||
|
{
|
||||||
|
if (replacement == NULL) replacement = "";
|
||||||
|
|
||||||
|
char *insertPoint = NULL; // Next insert point
|
||||||
|
char *tempPtr = NULL; // Temp pointer
|
||||||
|
int textLen = 0; // Text string length
|
||||||
|
int searchLen = 0; // Search string length of (the string to remove)
|
||||||
|
int replaceLen = 0; // Replacement length (the string to replace by)
|
||||||
|
int lastReplacePos = 0; // Distance between next search and end of last replace
|
||||||
|
int count = 0; // Number of replacements
|
||||||
|
|
||||||
|
textLen = TextLength(text);
|
||||||
|
searchLen = TextLength(search);
|
||||||
|
replaceLen = TextLength(replacement);
|
||||||
|
|
||||||
|
// Count the number of replacements needed
|
||||||
|
insertPoint = (char *)text;
|
||||||
|
for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen;
|
||||||
|
|
||||||
|
if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||||
|
{
|
||||||
|
// TODO: Allow copying data replaced up to maximum buffer size and stop
|
||||||
|
|
||||||
|
tempPtr = buffer; // Point to result start
|
||||||
|
|
||||||
|
// First time through the loop, all the variable are set correctly from here on,
|
||||||
|
// - 'temp' points to the end of the result string
|
||||||
|
// - 'insertPoint' points to the next occurrence of replace in text
|
||||||
|
// - 'text' points to the remainder of text after "end of replace"
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
insertPoint = (char *)strstr(text, search);
|
||||||
|
lastReplacePos = (int)(insertPoint - text);
|
||||||
|
|
||||||
|
memcpy(tempPtr, text, lastReplacePos);
|
||||||
|
tempPtr += lastReplacePos;
|
||||||
|
|
||||||
|
if (replaceLen > 0)
|
||||||
|
{
|
||||||
|
memcpy(tempPtr, replacement, replaceLen);
|
||||||
|
tempPtr += replaceLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
text += (lastReplacePos + searchLen); // Move to next "end of replace"
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy remaind text part after replacement to result (pointed by moving temp)
|
||||||
|
// NOTE: Text pointer internal copy has been updated along the process
|
||||||
|
strncpy(tempPtr, text, TextLength(text));
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace text string
|
||||||
|
// REQUIRES: strstr(), strncpy()
|
||||||
|
// WARNING: Allocated memory must be manually freed
|
||||||
|
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
@ -1825,11 +1889,46 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace text between two specific strings
|
||||||
|
// REQUIRES: strncpy()
|
||||||
|
// NOTE: If (replacement == NULL) removes "begin"[ ]"end" text
|
||||||
|
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (begin != NULL) && (end != NULL))
|
||||||
|
{
|
||||||
|
int beginIndex = TextFindIndex(text, begin);
|
||||||
|
|
||||||
|
if (beginIndex > -1)
|
||||||
|
{
|
||||||
|
int beginLen = TextLength(begin);
|
||||||
|
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
||||||
|
|
||||||
|
if (endIndex > -1)
|
||||||
|
{
|
||||||
|
endIndex += (beginIndex + beginLen);
|
||||||
|
|
||||||
|
int textLen = TextLength(text);
|
||||||
|
int replaceLen = (replacement == NULL)? 0 : TextLength(replacement);
|
||||||
|
//int toreplaceLen = endIndex - beginIndex - beginLen;
|
||||||
|
|
||||||
|
strncpy(buffer, text, beginIndex + beginLen); // Copy first text part
|
||||||
|
if (replacement != NULL) strncpy(buffer + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided)
|
||||||
|
strncpy(buffer + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace text between two specific strings
|
// Replace text between two specific strings
|
||||||
// REQUIRES: strncpy()
|
// REQUIRES: strncpy()
|
||||||
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
||||||
// WARNING: Returned string must be freed by user
|
// WARNING: Returned string must be freed by user
|
||||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
@ -1864,6 +1963,34 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
|
||||||
// Insert text in a specific position, moves all text forward
|
// Insert text in a specific position, moves all text forward
|
||||||
// WARNING: Allocated memory must be manually freed
|
// WARNING: Allocated memory must be manually freed
|
||||||
char *TextInsert(const char *text, const char *insert, int position)
|
char *TextInsert(const char *text, const char *insert, int position)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
if ((text != NULL) && (insert != NULL))
|
||||||
|
{
|
||||||
|
int textLen = TextLength(text);
|
||||||
|
int insertLen = TextLength(insert);
|
||||||
|
|
||||||
|
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||||
|
{
|
||||||
|
// TODO: Allow copying data inserted up to maximum buffer size and stop
|
||||||
|
|
||||||
|
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
||||||
|
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
||||||
|
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
|
||||||
|
|
||||||
|
buffer[textLen + insertLen] = '\0'; // Add EOL
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert text in a specific position, moves all text forward
|
||||||
|
// WARNING: Allocated memory must be manually freed
|
||||||
|
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
|
|
@ -2265,7 +2392,6 @@ int GetCodepoint(const char *text, int *codepointSize)
|
||||||
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
||||||
*codepointSize = 1;
|
*codepointSize = 1;
|
||||||
if (text == NULL) return codepoint;
|
if (text == NULL) return codepoint;
|
||||||
|
|
|
||||||
125
src/rtextures.c
125
src/rtextures.c
|
|
@ -3,31 +3,31 @@
|
||||||
* rtextures - Basic functions to load and draw textures
|
* rtextures - Basic functions to load and draw textures
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define SUPPORT_MODULE_RTEXTURES
|
* #define SUPPORT_MODULE_RTEXTURES 1
|
||||||
* rtextures module is included in the build
|
* rtextures module is included in the build
|
||||||
*
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_BMP
|
* #define SUPPORT_FILEFORMAT_BMP 1
|
||||||
* #define SUPPORT_FILEFORMAT_PNG
|
* #define SUPPORT_FILEFORMAT_PNG 1
|
||||||
* #define SUPPORT_FILEFORMAT_TGA
|
* #define SUPPORT_FILEFORMAT_TGA 0
|
||||||
* #define SUPPORT_FILEFORMAT_JPG
|
* #define SUPPORT_FILEFORMAT_JPG 0
|
||||||
* #define SUPPORT_FILEFORMAT_GIF
|
* #define SUPPORT_FILEFORMAT_GIF 1
|
||||||
* #define SUPPORT_FILEFORMAT_QOI
|
* #define SUPPORT_FILEFORMAT_QOI 1
|
||||||
* #define SUPPORT_FILEFORMAT_PSD
|
* #define SUPPORT_FILEFORMAT_PSD 0
|
||||||
* #define SUPPORT_FILEFORMAT_HDR
|
* #define SUPPORT_FILEFORMAT_HDR 0
|
||||||
* #define SUPPORT_FILEFORMAT_PIC
|
* #define SUPPORT_FILEFORMAT_PIC 0
|
||||||
* #define SUPPORT_FILEFORMAT_PNM
|
* #define SUPPORT_FILEFORMAT_PNM 0
|
||||||
* #define SUPPORT_FILEFORMAT_DDS
|
* #define SUPPORT_FILEFORMAT_DDS 1
|
||||||
* #define SUPPORT_FILEFORMAT_PKM
|
* #define SUPPORT_FILEFORMAT_PKM 0
|
||||||
* #define SUPPORT_FILEFORMAT_KTX
|
* #define SUPPORT_FILEFORMAT_KTX 0
|
||||||
* #define SUPPORT_FILEFORMAT_PVR
|
* #define SUPPORT_FILEFORMAT_PVR 0
|
||||||
* #define SUPPORT_FILEFORMAT_ASTC
|
* #define SUPPORT_FILEFORMAT_ASTC 0
|
||||||
* Select desired fileformats to be supported for image data loading. Some of those formats are
|
* Selected desired fileformats to be supported for image data loading. Some of those formats are
|
||||||
* supported by default, to remove support, comment unrequired #define in this module
|
* supported by default, to remove support, #define as 0 in this module or your build system
|
||||||
*
|
*
|
||||||
* #define SUPPORT_IMAGE_EXPORT
|
* #define SUPPORT_IMAGE_EXPORT 1
|
||||||
* Support image export in multiple file formats
|
* Support image export in multiple file formats
|
||||||
*
|
*
|
||||||
* #define SUPPORT_IMAGE_GENERATION
|
* #define SUPPORT_IMAGE_GENERATION 1
|
||||||
* Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
|
* Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
|
|
@ -366,7 +366,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load animated image data
|
// Load animated image data from memory
|
||||||
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
|
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
|
||||||
// - Number of frames is returned through 'frames' parameter
|
// - Number of frames is returned through 'frames' parameter
|
||||||
// - All frames are returned in RGBA format
|
// - All frames are returned in RGBA format
|
||||||
|
|
@ -376,8 +376,7 @@ Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileDat
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
int frameCount = 0;
|
int frameCount = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; // Security check
|
||||||
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;
|
|
||||||
|
|
||||||
#if SUPPORT_FILEFORMAT_GIF
|
#if SUPPORT_FILEFORMAT_GIF
|
||||||
if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0))
|
if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0))
|
||||||
|
|
@ -581,7 +580,7 @@ Image LoadImageFromTexture(Texture2D texture)
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load image from screen buffer and (screenshot)
|
// Load image from screen buffer (screenshot)
|
||||||
Image LoadImageFromScreen(void)
|
Image LoadImageFromScreen(void)
|
||||||
{
|
{
|
||||||
Image image = { 0 };
|
Image image = { 0 };
|
||||||
|
|
@ -621,8 +620,7 @@ bool ExportImage(Image image, const char *fileName)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; // Security check
|
||||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result;
|
|
||||||
|
|
||||||
#if SUPPORT_IMAGE_EXPORT
|
#if SUPPORT_IMAGE_EXPORT
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
|
|
@ -709,8 +707,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
||||||
unsigned char *fileData = NULL;
|
unsigned char *fileData = NULL;
|
||||||
*dataSize = 0;
|
*dataSize = 0;
|
||||||
|
|
||||||
// Security check for input data
|
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return fileData; // Security check
|
||||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return NULL;
|
|
||||||
|
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
|
|
||||||
|
|
@ -734,7 +731,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
||||||
// Export image as code file (.h) defining an array of bytes
|
// Export image as code file (.h) defining an array of bytes
|
||||||
bool ExportImageAsCode(Image image, const char *fileName)
|
bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool result = false;
|
||||||
|
|
||||||
#ifndef TEXT_BYTES_PER_LINE
|
#ifndef TEXT_BYTES_PER_LINE
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
|
|
@ -774,14 +771,14 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
||||||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
||||||
|
|
||||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||||
success = SaveFileText(fileName, txtData);
|
result = SaveFileText(fileName, txtData);
|
||||||
|
|
||||||
RL_FREE(txtData);
|
RL_FREE(txtData);
|
||||||
|
|
||||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||||
|
|
||||||
return success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -1536,8 +1533,7 @@ Image ImageFromChannel(Image image, int selectedChannel)
|
||||||
{
|
{
|
||||||
Image result = { 0 };
|
Image result = { 0 };
|
||||||
|
|
||||||
// Security check to avoid program crash
|
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; // Security check
|
||||||
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result;
|
|
||||||
|
|
||||||
// Check selected channel is valid
|
// Check selected channel is valid
|
||||||
if (selectedChannel < 0)
|
if (selectedChannel < 0)
|
||||||
|
|
@ -1579,7 +1575,7 @@ Image ImageFromChannel(Image image, int selectedChannel)
|
||||||
// Check for RGBA formats
|
// Check for RGBA formats
|
||||||
if (selectedChannel > 3)
|
if (selectedChannel > 3)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (rgba). Setting channel to alpha.");
|
TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (RGBA). Setting channel to alpha.");
|
||||||
selectedChannel = 3;
|
selectedChannel = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2799,7 +2795,7 @@ void ImageColorGrayscale(Image *image)
|
||||||
|
|
||||||
// Modify image color: contrast
|
// Modify image color: contrast
|
||||||
// NOTE: Contrast values between -100 and 100
|
// NOTE: Contrast values between -100 and 100
|
||||||
void ImageColorContrast(Image *image, float contrast)
|
void ImageColorContrast(Image *image, int contrast)
|
||||||
{
|
{
|
||||||
// Security check to avoid program crash
|
// Security check to avoid program crash
|
||||||
if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
|
if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
|
||||||
|
|
@ -2807,8 +2803,8 @@ void ImageColorContrast(Image *image, float contrast)
|
||||||
if (contrast < -100) contrast = -100;
|
if (contrast < -100) contrast = -100;
|
||||||
if (contrast > 100) contrast = 100;
|
if (contrast > 100) contrast = 100;
|
||||||
|
|
||||||
contrast = (100.0f + contrast)/100.0f;
|
float factor = (float)(100.0f + contrast)/100.0f;
|
||||||
contrast *= contrast;
|
factor *= factor;
|
||||||
|
|
||||||
Color *pixels = LoadImageColors(*image);
|
Color *pixels = LoadImageColors(*image);
|
||||||
|
|
||||||
|
|
@ -2816,7 +2812,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||||
{
|
{
|
||||||
float pR = (float)pixels[i].r/255.0f;
|
float pR = (float)pixels[i].r/255.0f;
|
||||||
pR -= 0.5f;
|
pR -= 0.5f;
|
||||||
pR *= contrast;
|
pR *= factor;
|
||||||
pR += 0.5f;
|
pR += 0.5f;
|
||||||
pR *= 255;
|
pR *= 255;
|
||||||
if (pR < 0) pR = 0;
|
if (pR < 0) pR = 0;
|
||||||
|
|
@ -2824,7 +2820,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||||
|
|
||||||
float pG = (float)pixels[i].g/255.0f;
|
float pG = (float)pixels[i].g/255.0f;
|
||||||
pG -= 0.5f;
|
pG -= 0.5f;
|
||||||
pG *= contrast;
|
pG *= factor;
|
||||||
pG += 0.5f;
|
pG += 0.5f;
|
||||||
pG *= 255;
|
pG *= 255;
|
||||||
if (pG < 0) pG = 0;
|
if (pG < 0) pG = 0;
|
||||||
|
|
@ -2832,7 +2828,7 @@ void ImageColorContrast(Image *image, float contrast)
|
||||||
|
|
||||||
float pB = (float)pixels[i].b/255.0f;
|
float pB = (float)pixels[i].b/255.0f;
|
||||||
pB -= 0.5f;
|
pB -= 0.5f;
|
||||||
pB *= contrast;
|
pB *= factor;
|
||||||
pB += 0.5f;
|
pB += 0.5f;
|
||||||
pB *= 255;
|
pB *= 255;
|
||||||
if (pB < 0) pB = 0;
|
if (pB < 0) pB = 0;
|
||||||
|
|
@ -2937,7 +2933,7 @@ void ImageColorReplace(Image *image, Color color, Color replace)
|
||||||
// NOTE: Memory allocated should be freed using UnloadImageColors();
|
// NOTE: Memory allocated should be freed using UnloadImageColors();
|
||||||
Color *LoadImageColors(Image image)
|
Color *LoadImageColors(Image image)
|
||||||
{
|
{
|
||||||
if ((image.width == 0) || (image.height == 0)) return NULL;
|
if ((image.width == 0) || (image.height == 0)) return NULL; // Security check
|
||||||
|
|
||||||
Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
|
Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
|
||||||
|
|
||||||
|
|
@ -3734,7 +3730,14 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangle lines within an image
|
// Draw rectangle lines within an image
|
||||||
void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color)
|
void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color)
|
||||||
|
{
|
||||||
|
Rectangle rec = { posX, posY, width, height };
|
||||||
|
ImageDrawRectangleLinesEx(dst, rec, 1, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw rectangle lines within an image with extended parameters
|
||||||
|
void ImageDrawRectangleLinesEx(Image *dst, Rectangle rec, int thick, Color color)
|
||||||
{
|
{
|
||||||
ImageDrawRectangle(dst, (int)rec.x, (int)rec.y, (int)rec.width, thick, color);
|
ImageDrawRectangle(dst, (int)rec.x, (int)rec.y, (int)rec.width, thick, color);
|
||||||
ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + thick), thick, (int)(rec.height - thick*2), color);
|
ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + thick), thick, (int)(rec.height - thick*2), color);
|
||||||
|
|
@ -3810,7 +3813,7 @@ void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color col
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw triangle with interpolated colors within an image
|
// Draw triangle with interpolated colors within an image
|
||||||
void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
|
void ImageDrawTriangleGradient(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
|
||||||
{
|
{
|
||||||
// Calculate the 2D bounding box of the triangle
|
// Calculate the 2D bounding box of the triangle
|
||||||
// Determine the minimum and maximum x and y coordinates of the triangle vertices
|
// Determine the minimum and maximum x and y coordinates of the triangle vertices
|
||||||
|
|
@ -4628,7 +4631,7 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws a texture (or part of it) that stretches or shrinks nicely using n-patch info
|
// Draw a texture (or part of it) that stretches or shrinks nicely using n-patch info
|
||||||
void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint)
|
void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint)
|
||||||
{
|
{
|
||||||
if (texture.id > 0)
|
if (texture.id > 0)
|
||||||
|
|
@ -4903,11 +4906,11 @@ Vector3 ColorToHSV(Color color)
|
||||||
float max = 0.0f;
|
float max = 0.0f;
|
||||||
float delta = 0.0f;
|
float delta = 0.0f;
|
||||||
|
|
||||||
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
min = (rgb.x < rgb.y)? rgb.x : rgb.y;
|
||||||
min = min < rgb.z? min : rgb.z;
|
min = (min < rgb.z)? min : rgb.z;
|
||||||
|
|
||||||
max = rgb.x > rgb.y? rgb.x : rgb.y;
|
max = (rgb.x > rgb.y)? rgb.x : rgb.y;
|
||||||
max = max > rgb.z? max : rgb.z;
|
max = (max > rgb.z)? max : rgb.z;
|
||||||
|
|
||||||
hsv.z = max; // Value
|
hsv.z = max; // Value
|
||||||
delta = max - min;
|
delta = max - min;
|
||||||
|
|
@ -5093,7 +5096,7 @@ Color ColorAlpha(Color color, float alpha)
|
||||||
// Get src alpha-blended into dst color with tint
|
// Get src alpha-blended into dst color with tint
|
||||||
Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
{
|
{
|
||||||
Color out = WHITE;
|
Color result = WHITE;
|
||||||
|
|
||||||
// Apply color tint to source color
|
// Apply color tint to source color
|
||||||
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
||||||
|
|
@ -5104,24 +5107,24 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
//#define COLORALPHABLEND_FLOAT
|
//#define COLORALPHABLEND_FLOAT
|
||||||
#define COLORALPHABLEND_INTEGERS
|
#define COLORALPHABLEND_INTEGERS
|
||||||
#if defined(COLORALPHABLEND_INTEGERS)
|
#if defined(COLORALPHABLEND_INTEGERS)
|
||||||
if (src.a == 0) out = dst;
|
if (src.a == 0) result = dst;
|
||||||
else if (src.a == 255) out = src;
|
else if (src.a == 255) result = src;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account
|
unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account
|
||||||
out.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
result.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
||||||
|
|
||||||
if (out.a > 0)
|
if (result.a > 0)
|
||||||
{
|
{
|
||||||
out.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
out.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
out.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
result.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(COLORALPHABLEND_FLOAT)
|
#if defined(COLORALPHABLEND_FLOAT)
|
||||||
if (src.a == 0) out = dst;
|
if (src.a == 0) result = dst;
|
||||||
else if (src.a == 255) out = src;
|
else if (src.a == 255) result = src;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector4 fdst = ColorNormalize(dst);
|
Vector4 fdst = ColorNormalize(dst);
|
||||||
|
|
@ -5138,11 +5141,11 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||||
fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
|
fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
out = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
result = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return out;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
|
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
Copyright (c) 2026 Ramon Santamaria (@raysan5)
|
||||||
|
|
||||||
This software is provided "as-is", without any express or implied warranty. In no event
|
This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
will the authors be held liable for any damages arising from the use of this software.
|
will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# raylib makefile for Desktop platforms, Web (Wasm), Raspberry Pi (DRM mode) and Android
|
# raylib makefile for Desktop platforms, Web (Wasm), Raspberry Pi (DRM mode) and Android
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
|
||||||
#
|
#
|
||||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
# will the authors be held liable for any damages arising from the use of this software.
|
# will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB
|
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB
|
||||||
|
|
||||||
#define REXM_MAX_RESOURCE_PATHS 256
|
#define REXM_MAX_RESOURCE_PATHS 256
|
||||||
|
#define REXM_MAX_RESOURCE_PATH_LENGTH 256
|
||||||
|
|
||||||
// Create local commit with changes on example renaming
|
// Create local commit with changes on example renaming
|
||||||
//#define RENAME_AUTO_COMMIT_CREATION
|
//#define RENAME_AUTO_COMMIT_CREATION
|
||||||
|
|
@ -469,12 +470,12 @@ int main(int argc, char *argv[])
|
||||||
int exIndex = TextFindIndex(exText, "/****************");
|
int exIndex = TextFindIndex(exText, "/****************");
|
||||||
|
|
||||||
// Update required info with some defaults
|
// Update required info with some defaults
|
||||||
exTextUpdated[0] = TextReplace(exText + exIndex, "<module>", exCategory);
|
exTextUpdated[0] = TextReplaceAlloc(exText + exIndex, "<module>", exCategory);
|
||||||
exTextUpdated[1] = TextReplace(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
exTextUpdated[1] = TextReplaceAlloc(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
||||||
//TextReplace(newExample, "<user_name>", "Ray");
|
//TextReplaceAlloc(newExample, "<user_name>", "Ray");
|
||||||
//TextReplace(newExample, "@<user_github>", "@raysan5");
|
//TextReplaceAlloc(newExample, "@<user_github>", "@raysan5");
|
||||||
//TextReplace(newExample, "<year_created>", 2025);
|
//TextReplaceAlloc(newExample, "<year_created>", 2026);
|
||||||
//TextReplace(newExample, "<year_updated>", 2025);
|
//TextReplaceAlloc(newExample, "<year_updated>", 2026);
|
||||||
|
|
||||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]);
|
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]);
|
||||||
for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; }
|
for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; }
|
||||||
|
|
@ -541,8 +542,6 @@ int main(int argc, char *argv[])
|
||||||
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n");
|
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n");
|
||||||
}
|
}
|
||||||
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated));
|
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated));
|
||||||
|
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -863,9 +862,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
for (int v = 0; v < 3; v++)
|
for (int v = 0; v < 3; v++)
|
||||||
{
|
{
|
||||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]));
|
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]))));
|
||||||
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated));
|
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r]));
|
else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r]));
|
||||||
|
|
@ -1164,7 +1161,6 @@ int main(int argc, char *argv[])
|
||||||
// Logging missing resources for convenience
|
// Logging missing resources for convenience
|
||||||
LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated);
|
LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated);
|
||||||
}
|
}
|
||||||
RL_FREE(resPathUpdated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1272,8 +1268,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// NOTE: Some examples should be excluded from VS2022 solution because
|
// NOTE: Some examples should be excluded from VS2022 solution because
|
||||||
// they have specific platform/linkage requirements:
|
// they have specific platform/linkage requirements:
|
||||||
if ((strcmp(exInfo->name, "web_basic_window") == 0) ||
|
if (strcmp(exInfo->name, "raylib_opengl_interop") == 0) continue;
|
||||||
(strcmp(exInfo->name, "raylib_opengl_interop") == 0)) continue;
|
|
||||||
|
|
||||||
// Review: Add: raylib/projects/VS2022/examples/<category>_example_name.vcxproj
|
// Review: Add: raylib/projects/VS2022/examples/<category>_example_name.vcxproj
|
||||||
// Review: Add: raylib/projects/VS2022/raylib.sln
|
// Review: Add: raylib/projects/VS2022/raylib.sln
|
||||||
|
|
@ -1577,13 +1572,13 @@ int main(int argc, char *argv[])
|
||||||
" SaveFileText(\"outputLogFileName\", logText);\n"
|
" SaveFileText(\"outputLogFileName\", logText);\n"
|
||||||
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
|
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
|
||||||
" return 0";
|
" return 0";
|
||||||
char *returnReplaceTextUpdated = TextReplace(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
char *returnReplaceTextUpdated = TextReplaceAlloc(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
||||||
|
|
||||||
char *srcTextUpdated[4] = { 0 };
|
char *srcTextUpdated[4] = { 0 };
|
||||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||||
srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
srcTextUpdated[3] = TextReplaceAlloc(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
||||||
MemFree(returnReplaceTextUpdated);
|
MemFree(returnReplaceTextUpdated);
|
||||||
UnloadFileText(srcText);
|
UnloadFileText(srcText);
|
||||||
|
|
||||||
|
|
@ -1633,9 +1628,9 @@ int main(int argc, char *argv[])
|
||||||
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
||||||
|
|
||||||
char *srcTextUpdated[3] = { 0 };
|
char *srcTextUpdated[3] = { 0 };
|
||||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||||
UnloadFileText(srcText);
|
UnloadFileText(srcText);
|
||||||
|
|
||||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
||||||
|
|
@ -1669,7 +1664,7 @@ int main(int argc, char *argv[])
|
||||||
FileRemove(TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName));
|
FileRemove(TextFormat("%s/%s/%s.original.c", exBasePath, exCategory, exName));
|
||||||
|
|
||||||
// STEP 3: Run example with required arguments
|
// STEP 3: Run example with required arguments
|
||||||
// NOTE: Not easy to retrieve process return value from system(), it's platform dependant
|
// NOTE: Not easy to retrieve process return value from system(), it's platform dependent
|
||||||
ChangeDirectory(TextFormat("%s/%s", exBasePath, exCategory));
|
ChangeDirectory(TextFormat("%s/%s", exBasePath, exCategory));
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
@ -1879,7 +1874,7 @@ int main(int argc, char *argv[])
|
||||||
printf("\n////////////////////////////////////////////////////////////////////////////////////////////\n");
|
printf("\n////////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||||
printf("// //\n");
|
printf("// //\n");
|
||||||
printf("// rexm [raylib examples manager] - A simple command-line tool to manage raylib examples //\n");
|
printf("// rexm [raylib examples manager] - A simple command-line tool to manage raylib examples //\n");
|
||||||
printf("// powered by raylib v5.6-dev //\n");
|
printf("// powered by raylib v6.0 //\n");
|
||||||
printf("// //\n");
|
printf("// //\n");
|
||||||
printf("// Copyright (c) 2025-2026 Ramon Santamaria (@raysan5) //\n");
|
printf("// Copyright (c) 2025-2026 Ramon Santamaria (@raysan5) //\n");
|
||||||
printf("// //\n");
|
printf("// //\n");
|
||||||
|
|
@ -2042,7 +2037,7 @@ static int UpdateRequiredFiles(void)
|
||||||
// In this case, we focus on web building for: glsl100
|
// In this case, we focus on web building for: glsl100
|
||||||
if (TextFindIndex(resPaths[r], "glsl%i") > -1)
|
if (TextFindIndex(resPaths[r], "glsl%i") > -1)
|
||||||
{
|
{
|
||||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", "glsl100");
|
char *resPathUpdated = TextReplaceAlloc(resPaths[r], "glsl%i", "glsl100");
|
||||||
memset(resPaths[r], 0, 256);
|
memset(resPaths[r], 0, 256);
|
||||||
strcpy(resPaths[r], resPathUpdated);
|
strcpy(resPaths[r], resPathUpdated);
|
||||||
RL_FREE(resPathUpdated);
|
RL_FREE(resPathUpdated);
|
||||||
|
|
@ -2147,7 +2142,7 @@ static int UpdateRequiredFiles(void)
|
||||||
{
|
{
|
||||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount));
|
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount));
|
||||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex,
|
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex,
|
||||||
"Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.\n\n");
|
"Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.\n\n");
|
||||||
}
|
}
|
||||||
else if (i == 6) // "audio"
|
else if (i == 6) // "audio"
|
||||||
{
|
{
|
||||||
|
|
@ -2498,25 +2493,21 @@ static void SortExampleByName(rlExampleInfo *items, int count)
|
||||||
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare);
|
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan resource paths in example file
|
// Scan asset paths from a source code file (raylib)
|
||||||
// WARNING: Supported resource file extensions is hardcoded by used file types
|
// WARNING: Supported asset file extensions are hardcoded by used file types
|
||||||
// but new examples could require other file extensions to be added,
|
// but new examples could require other file extensions to be added
|
||||||
// maybe it should look for '.xxx")' patterns instead
|
static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCount)
|
||||||
// TODO: WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png, ...
|
|
||||||
static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
|
||||||
{
|
{
|
||||||
#define REXM_MAX_RESOURCE_PATH_LEN 256
|
|
||||||
|
|
||||||
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **));
|
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **));
|
||||||
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LEN, sizeof(char));
|
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LENGTH, sizeof(char));
|
||||||
|
|
||||||
int resCounter = 0;
|
int resCounter = 0;
|
||||||
char *code = LoadFileText(filePath);
|
char *code = LoadFileText(srcFilePath);
|
||||||
|
|
||||||
if (code != NULL)
|
if (code != NULL)
|
||||||
{
|
{
|
||||||
// Resources extensions to check
|
// Resources extensions to check
|
||||||
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".xm", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
||||||
const int extCount = sizeof(exts)/sizeof(char *);
|
const int extCount = sizeof(exts)/sizeof(char *);
|
||||||
|
|
||||||
char *ptr = code;
|
char *ptr = code;
|
||||||
|
|
@ -2542,9 +2533,9 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
||||||
!((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before ""
|
!((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before ""
|
||||||
{
|
{
|
||||||
int len = (int)(end - start);
|
int len = (int)(end - start);
|
||||||
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LEN))
|
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LENGTH))
|
||||||
{
|
{
|
||||||
char buffer[REXM_MAX_RESOURCE_PATH_LEN] = { 0 };
|
char buffer[REXM_MAX_RESOURCE_PATH_LENGTH] = { 0 };
|
||||||
strncpy(buffer, start, len);
|
strncpy(buffer, start, len);
|
||||||
buffer[len] = '\0';
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
|
@ -2580,6 +2571,29 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
||||||
UnloadFileText(code);
|
UnloadFileText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png
|
||||||
|
// So doing a recursive pass to scan possible files with second resources
|
||||||
|
int currentAssetCounter = resCounter;
|
||||||
|
for (int i = 0; i < currentAssetCounter; i++)
|
||||||
|
{
|
||||||
|
if (IsFileExtension(paths[i], ".fnt;.gltf"))
|
||||||
|
{
|
||||||
|
int assetCount2 = 0;
|
||||||
|
// ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are override
|
||||||
|
char **assetPaths2 = LoadExampleResourcePaths(TextFormat("%s/%s", GetDirectoryPath(srcFilePath), paths[i]), &assetCount2);
|
||||||
|
|
||||||
|
for (int j = 0; j < assetCount2; j++)
|
||||||
|
{
|
||||||
|
strcpy(paths[resCounter], TextFormat("%s/%s", GetDirectoryPath(paths[i]) + 2, assetPaths2[j]));
|
||||||
|
resCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadExampleResourcePaths(assetPaths2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
*resPathCount = resCounter;
|
*resPathCount = resCounter;
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
@ -2815,7 +2829,7 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
|
|
||||||
// Update example header title (line #3 - ALWAYS)
|
// Update example header title (line #3 - ALWAYS)
|
||||||
// String: "* raylib [shaders] example - texture drawing"
|
// String: "* raylib [shaders] example - texture drawing"
|
||||||
exTextUpdated[0] = TextReplaceBetween(exTextUpdatedPtr, "* raylib [", "\n",
|
exTextUpdated[0] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* raylib [", "\n",
|
||||||
TextFormat("%s] example - %s", info->category, exNameFormated));
|
TextFormat("%s] example - %s", info->category, exNameFormated));
|
||||||
if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0];
|
if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0];
|
||||||
|
|
||||||
|
|
@ -2829,13 +2843,13 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
if (i < info->stars) strcpy(starsText + 3*i, "★");
|
if (i < info->stars) strcpy(starsText + 3*i, "★");
|
||||||
else strcpy(starsText + 3*i, "☆");
|
else strcpy(starsText + 3*i, "☆");
|
||||||
}
|
}
|
||||||
exTextUpdated[1] = TextReplaceBetween(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
exTextUpdated[1] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
||||||
TextFormat("%s] %i", starsText, info->stars));
|
TextFormat("%s] %i", starsText, info->stars));
|
||||||
if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1];
|
if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1];
|
||||||
|
|
||||||
// Update example creation/update raylib versions
|
// Update example creation/update raylib versions
|
||||||
// String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
// String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
||||||
exTextUpdated[2] = TextReplaceBetween(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
exTextUpdated[2] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
||||||
TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated));
|
TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated));
|
||||||
if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2];
|
if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2];
|
||||||
|
|
||||||
|
|
@ -2843,27 +2857,27 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
||||||
// String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)"
|
// String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)"
|
||||||
if (info->yearCreated == info->yearReviewed)
|
if (info->yearCreated == info->yearReviewed)
|
||||||
{
|
{
|
||||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||||
TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub));
|
TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||||
TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub));
|
TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update window title
|
// Update window title
|
||||||
// String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");"
|
// String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");"
|
||||||
exTextUpdated[4] = TextReplaceBetween(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
exTextUpdated[4] = TextReplaceBetweenAlloc(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
||||||
TextFormat("raylib [%s] example - %s", info->category, exNameFormated));
|
TextFormat("raylib [%s] example - %s", info->category, exNameFormated));
|
||||||
if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4];
|
if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4];
|
||||||
|
|
||||||
// Update contributors names
|
// Update contributors names
|
||||||
// String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)"
|
// String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)"
|
||||||
// WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found)
|
// WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found)
|
||||||
exTextUpdated[5] = TextReplaceBetween(exTextUpdatedPtr, "* Example contributed by ", ")",
|
exTextUpdated[5] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example contributed by ", ")",
|
||||||
TextFormat("%s (@%s", info->author, info->authorGitHub));
|
TextFormat("%s (@%s", info->author, info->authorGitHub));
|
||||||
if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5];
|
if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5];
|
||||||
|
|
||||||
|
|
@ -2910,14 +2924,14 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath)
|
||||||
UnloadFileText(exText);
|
UnloadFileText(exText);
|
||||||
|
|
||||||
// Update example.html required text
|
// Update example.html required text
|
||||||
exHtmlTextUpdated[0] = TextReplace(exHtmlText, "raylib web game", exTitle);
|
exHtmlTextUpdated[0] = TextReplaceAlloc(exHtmlText, "raylib web game", exTitle);
|
||||||
exHtmlTextUpdated[1] = TextReplace(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
exHtmlTextUpdated[1] = TextReplaceAlloc(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
||||||
exHtmlTextUpdated[2] = TextReplace(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
exHtmlTextUpdated[2] = TextReplaceAlloc(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
||||||
TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName));
|
TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName));
|
||||||
exHtmlTextUpdated[3] = TextReplace(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
exHtmlTextUpdated[3] = TextReplaceAlloc(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
||||||
TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
|
TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
|
||||||
exHtmlTextUpdated[4] = TextReplace(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
exHtmlTextUpdated[4] = TextReplaceAlloc(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
||||||
exHtmlTextUpdated[5] = TextReplace(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
exHtmlTextUpdated[5] = TextReplaceAlloc(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
||||||
TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
|
TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
|
||||||
|
|
||||||
SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]);
|
SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]);
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user