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

This commit is contained in:
ColleagueRiley 2024-12-24 15:02:19 -05:00
commit dbfc10ca72
47 changed files with 1872 additions and 907 deletions

View File

@ -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.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | | [raylib](https://github.com/raysan5/raylib) | **5.5** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [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 |
| [raylib-boo](https://github.com/Rabios/raylib-boo) | 3.7 | [Boo](http://boo-language.github.io) | 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-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.1-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT | | [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.1-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
@ -18,36 +18,41 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib | | [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 | | [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 | | [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 | | [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT | | [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
| [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) | **5.5** | [D](https://dlang.org) | Zlib |
| [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-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD |
| [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 |
| [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 |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.0** | [Go](https://golang.org) | Zlib | | [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib | | [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** | | [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 | | [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib | | [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT | | [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT | | [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
| [jaylib](https://github.com/electronstudio/jaylib/) | 4.5 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE | | [jaylib](https://github.com/electronstudio/jaylib/) | **5.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | | [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib | | [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** | | [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib | | [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 4.5 | [Lua](http://www.lua.org) | ISC | | [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC |
| [raylua](https://github.com/Rabios/raylua) | 4.0 | [Lua](http://www.lua.org) | MIT | | [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | MIT | | [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.0** | [nelua](https://nelua.io) | Zlib | | [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.0** | [nelua](https://nelua.io) | Zlib |
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 4.5 | [Ruby](https://www.ruby-lang.org/en) | Zlib | | [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
| [naylib](https://github.com/planetis-m/naylib) | **5.1-dev** | [Nim](https://nim-lang.org) | MIT | | [naylib](https://github.com/planetis-m/naylib) | **5.1-dev** | [Nim](https://nim-lang.org) | MIT |
| [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib | | [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib |
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.0** | [Odin](https://odin-lang.org) | BSD-3Clause | | [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | BSD-3Clause |
| [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 |
@ -55,25 +60,26 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [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 |
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 4.5 | [Python](https://www.python.org) | MIT | | [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-py](https://github.com/overdev/raylib-py) | 5.5 | [Python](https://www.python.org) | MIT | | [raylib-py](https://github.com/overdev/raylib-py) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT | | [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 4.6-dev | [pocketpy](https://pocketpy.dev) | MIT | | [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.1-dev | [pocketpy](https://pocketpy.dev) | MIT |
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | | [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | | [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [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) | 4.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.0** | [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 |
| [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) | 4.0 | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | | [racket-raylib](https://github.com/eutro/racket-raylib) | 4.0 | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT | | [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT | | [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.0** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | | [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
| [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-for-v](https://github.com/EmmaTheMartian/raylib-for-v) | 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) | **5.0** | [Vala](https://vala.dev) | Zlib |
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.0 | [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/Not-Nik/raylib-zig) | **5.0** | [Zig](https://ziglang.org) | MIT | | [raylib-zig](https://github.com/Not-Nik/raylib-zig) | **5.5** | [Zig](https://ziglang.org) | MIT |
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT | | [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib | | [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib | | [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
@ -84,6 +90,8 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause | | [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain | | [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT | | [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
### Utility Wrapers ### Utility Wrapers
@ -93,6 +101,7 @@ These are utility wrappers for specific languages, they are not required to use
| [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) | **5.5** | [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 |
### Older or Unmaintained Language Bindings ### Older or Unmaintained Language Bindings
@ -152,7 +161,7 @@ These are older raylib bindings that are more than 2 versions old or have not be
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) | | [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) | | [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) | | [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) | | [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) | | [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) | | [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) | | [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.12)
project(raylib) project(raylib)
# Avoid excessive expansion of variables in conditionals. In particular, if # Avoid excessive expansion of variables in conditionals. In particular, if

View File

@ -24,7 +24,7 @@ enum_option(USE_EXTERNAL_GLFW "OFF;IF_POSSIBLE;ON" "Link raylib against system G
option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF) 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") set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
include(ParseConfigHeader) include(ParseConfigHeader)

View File

@ -54,7 +54,7 @@ To open new issues for raylib (bug, enhancement, discussion...), just try to fol
- If applicable, attach some screenshot of the issue and a .zip file with the code sample and required resources. - If applicable, attach some screenshot of the issue and a .zip file with the code sample and required resources.
- On issue description, add a brackets tag about the raylib module that relates to this issue. - On issue description, add a brackets tag about the raylib module that relates to this issue.
If don't know which module, just report the issue, I will review it. If don't know which module, just report the issue, I will review it.
- You can check other issues to see how is being done! - You can check other issues to see how it's being done!
### Sending a Pull-Request ### Sending a Pull-Request

2
FAQ.md
View File

@ -90,7 +90,7 @@ I personally consider raylib a graphics library with some high-level features ra
### What does raylib provide that other engines or libraries don't? ### What does raylib provide that other engines or libraries don't?
I would say "simplicity" and "enjoyment" at a really low level of coding but actually is up to the user to discover it, to try it and to see if it fits their needs. raylib is not good for everyone but it's worth a try. I would say "simplicity" and "enjoyment" at a really low level of coding but actually it is up to the user to discover it, to try it and to see if it fits their needs. raylib is not good for everyone but it's worth a try.
### How does raylib compare to Unity/Unreal/Godot? ### How does raylib compare to Unity/Unreal/Godot?

View File

@ -401,6 +401,7 @@ pub fn build(b: *std.Build) !void {
const lib = try compileRaylib(b, target, optimize, Options.getOptions(b)); const lib = try compileRaylib(b, target, optimize, Options.getOptions(b));
lib.installHeader(b.path("src/raylib.h"), "raylib.h"); lib.installHeader(b.path("src/raylib.h"), "raylib.h");
lib.installHeader(b.path("src/rcamera.h"), "rcamera.h");
lib.installHeader(b.path("src/raymath.h"), "raymath.h"); lib.installHeader(b.path("src/raymath.h"), "raymath.h");
lib.installHeader(b.path("src/rlgl.h"), "rlgl.h"); lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");

View File

@ -12,7 +12,6 @@ endif()
# Also adding only on desktop (web also uses glfw but it is more limited and is added using an emcc linker flag) # Also adding only on desktop (web also uses glfw but it is more limited and is added using an emcc linker flag)
if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW STREQUAL "ON" AND "${PLATFORM}" MATCHES "Desktop") if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW STREQUAL "ON" AND "${PLATFORM}" MATCHES "Desktop")
MESSAGE(STATUS "Using raylib's GLFW") MESSAGE(STATUS "Using raylib's GLFW")
set(INTERNAL_GLFW ON CACHE INTERNAL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
@ -20,11 +19,6 @@ if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW STREQUAL "ON" AND "${PLATFORM}" MAT
set(GLFW_LIBRARY_TYPE "OBJECT" CACHE STRING "" FORCE) set(GLFW_LIBRARY_TYPE "OBJECT" CACHE STRING "" FORCE)
if (NOT BUILD_SHARED_LIBS)
message(STATUS "Enabling install of GLFW static libs because raylib will be built statically")
set(GLFW_INSTALL ON CACHE BOOL "" FORCE)
endif ()
add_subdirectory(external/glfw) add_subdirectory(external/glfw)
# Hide glfw's symbols when building a shared lib # Hide glfw's symbols when building a shared lib

View File

@ -18,8 +18,10 @@ endif ()
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}") join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file(../raylib.pc.in raylib.pc @ONLY) configure_file(../raylib.pc.in raylib.pc @ONLY)
configure_file(../cmake/raylib-config-version.cmake raylib-config-version.cmake @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/raylib.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/raylib.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
include(SetupCmakeConfig) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/raylib-config-version.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/raylib")
install(FILES ${PROJECT_SOURCE_DIR}/../cmake/raylib-config.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/raylib")
# populates raylib_{FOUND, INCLUDE_DIRS, LIBRARIES, LDFLAGS, DEFINITIONS} # populates raylib_{FOUND, INCLUDE_DIRS, LIBRARIES, LDFLAGS, DEFINITIONS}
include(PopulateConfigVariablesLocally) include(PopulateConfigVariablesLocally)

View File

@ -125,3 +125,7 @@ if (NOT GRAPHICS)
endif () endif ()
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY}) set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
if (${PLATFORM} MATCHES "Desktop")
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
endif ()

View File

@ -1,23 +0,0 @@
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
# Setup install of exported targets
install(EXPORT raylib-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/raylib
)
# Macro to write config
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/raylib-config-version.cmake"
VERSION ${raylib_VERSION}
COMPATIBILITY SameMajorVersion
)
# Setup install of version config
install(
FILES
"../cmake/raylib-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/raylib-config-version.cmake"
DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/raylib
)

View File

@ -0,0 +1,21 @@
set(PACKAGE_VERSION "@PROJECT_VERSION@")
if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
if(NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
set(PACKAGE_VERSION_COMPATIBLE TRUE)
else(NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif(NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "")
return()
endif()
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@")
math(EXPR installedBits "8 * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

View File

@ -1 +1,79 @@
include("${CMAKE_CURRENT_LIST_DIR}/raylib-targets.cmake") # - Try to find raylib
# Options:
# raylib_USE_STATIC_LIBS - OFF by default
# raylib_VERBOSE - OFF by default
# Once done, this defines a raylib target that can be passed to
# target_link_libraries as well as following variables:
#
# raylib_FOUND - System has raylib installed
# raylib_INCLUDE_DIRS - The include directories for the raylib header(s)
# raylib_LIBRARIES - The libraries needed to use raylib
# raylib_LDFLAGS - The linker flags needed with raylib
# raylib_DEFINITIONS - Compiler switches required for using raylib
if (NOT TARGET raylib)
set(XPREFIX PC_RAYLIB)
find_package(PkgConfig QUIET)
pkg_check_modules(${XPREFIX} QUIET raylib)
if (raylib_USE_STATIC_LIBS)
set(XPREFIX ${XPREFIX}_STATIC)
endif()
set(raylib_DEFINITIONS ${${XPREFIX}_CFLAGS})
find_path(raylib_INCLUDE_DIR
NAMES raylib.h
HINTS ${${XPREFIX}_INCLUDE_DIRS}
)
set(RAYLIB_NAMES raylib)
if (raylib_USE_STATIC_LIBS)
set(RAYLIB_NAMES libraylib.a raylib.lib ${RAYLIB_NAMES})
endif()
find_library(raylib_LIBRARY
NAMES ${RAYLIB_NAMES}
HINTS ${${XPREFIX}_LIBRARY_DIRS}
)
set(raylib_LIBRARIES ${raylib_LIBRARY})
set(raylib_LIBRARY_DIRS ${${XPREFIX}_LIBRARY_DIRS})
set(raylib_LIBRARY_DIR ${raylib_LIBRARY_DIRS})
set(raylib_INCLUDE_DIRS ${raylib_INCLUDE_DIR})
set(raylib_LDFLAGS ${${XPREFIX}_LDFLAGS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(raylib DEFAULT_MSG
raylib_LIBRARY
raylib_INCLUDE_DIR
)
mark_as_advanced(raylib_LIBRARY raylib_INCLUDE_DIR)
if (raylib_USE_STATIC_LIBS)
add_library(raylib STATIC IMPORTED GLOBAL)
else()
add_library(raylib SHARED IMPORTED GLOBAL)
endif()
string (REPLACE ";" " " raylib_LDFLAGS "${raylib_LDFLAGS}")
set_target_properties(raylib
PROPERTIES
IMPORTED_LOCATION "${raylib_LIBRARIES}"
IMPORTED_IMPLIB "${raylib_LIBRARIES}"
INTERFACE_INCLUDE_DIRECTORIES "${raylib_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${raylib_LDFLAGS}"
INTERFACE_COMPILE_OPTIONS "${raylib_DEFINITIONS}"
)
if (raylib_VERBOSE)
message(STATUS "raylib_FOUND: ${raylib_FOUND}")
message(STATUS "raylib_INCLUDE_DIRS: ${raylib_INCLUDE_DIRS}")
message(STATUS "raylib_LIBRARIES: ${raylib_LIBRARIES}")
message(STATUS "raylib_LDFLAGS: ${raylib_LDFLAGS}")
message(STATUS "raylib_DEFINITIONS: ${raylib_DEFINITIONS}")
endif()
endif()

View File

@ -56,10 +56,15 @@
# Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB, PLATFORM_WEB_RGFW # Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB, PLATFORM_WEB_RGFW
PLATFORM ?= PLATFORM_DESKTOP PLATFORM ?= PLATFORM_DESKTOP
ifeq ($(PLATFORM), PLATFORM_DESKTOP) ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW))
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW TARGET_PLATFORM := $(PLATFORM)
override PLATFORM = PLATFORM_DESKTOP
else else
TARGET_PLATFORM = $(PLATFORM) ifeq ($(PLATFORM), PLATFORM_DESKTOP)
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW
else
TARGET_PLATFORM = $(PLATFORM)
endif
endif endif
# Define required raylib variables # Define required raylib variables
@ -484,7 +489,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
endif endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
# Libraries for web (HTML5) compiling # Libraries for web (HTML5) compiling
LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.a LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.web.a
endif endif
# Define source code object files required # Define source code object files required

View File

@ -370,7 +370,7 @@ ifeq ($(PLATFORM),PLATFORM_DRM)
endif endif
ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
# Libraries for web (HTML5) compiling # Libraries for web (HTML5) compiling
LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.a LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.web.a
endif endif
# Define source code object files required # Define source code object files required

View File

@ -6,7 +6,8 @@
* *
* Example create by GreenSnakeLinux (@GreenSnakeLinux), * Example create by GreenSnakeLinux (@GreenSnakeLinux),
* lighter by oblerion (@oblerion) and * lighter by oblerion (@oblerion) and
* reviewed by Ramon Santamaria (@raysan5) * reviewed by Ramon Santamaria (@raysan5) and
* improved by danilwhale (@danilwhale)
* *
* 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
@ -17,6 +18,16 @@
#include "raylib.h" #include "raylib.h"
#include <math.h> #include <math.h>
typedef enum {
BUTTON_NONE = -1,
BUTTON_UP,
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_DOWN,
BUTTON_MAX
} PadButton;
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -29,24 +40,38 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls"); InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
const float dpadX = 90; Vector2 padPosition = { 100, 350 };
const float dpadY = 300; float buttonRadius = 30;
const float dpadRad = 25.0f;//radius of each pad
Color dpadColor = BLUE;
int dpadKeydown = -1;//-1 if not down, else 0,1,2,3
Vector2 buttonPositions[BUTTON_MAX] =
const float dpadCollider[4][2]= // collider array with x,y position
{ {
{dpadX,dpadY-dpadRad*1.5f},//up { padPosition.x,padPosition.y - buttonRadius*1.5f }, // Up
{dpadX-dpadRad*1.5f,dpadY},//left { padPosition.x - buttonRadius*1.5f, padPosition.y }, // Left
{dpadX+dpadRad*1.5f,dpadY},//right { padPosition.x + buttonRadius*1.5f, padPosition.y }, // Right
{dpadX,dpadY+dpadRad*1.5f}//down { padPosition.x, padPosition.y + buttonRadius*1.5f } // Down
}; };
const char dpadLabel[4]="XYBA";//label of Dpad
float playerX=100; const char *buttonLabels[BUTTON_MAX] =
float playerY=100; {
"Y", // Up
"X", // Left
"B", // Right
"A" // Down
};
Color buttonLabelColors[BUTTON_MAX] =
{
YELLOW, // Up
BLUE, // Left
RED, // Right
GREEN // Down
};
int pressedButton = BUTTON_NONE;
Vector2 inputPosition = { 0, 0 };
Vector2 playerPosition = { (float)screenWidth/2, (float)screenHeight/2 };
float playerSpeed = 75;
SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -54,63 +79,89 @@ int main(void)
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
dpadKeydown = -1; //reset if ((GetTouchPointCount() > 0))
int inputX = 0; {
int inputY = 0; // Use touch position
if(GetTouchPointCount()>0) inputPosition = GetTouchPosition(0);
{//use touch pos
inputX = GetTouchX();
inputY = GetTouchY();
} }
else else
{//use mouse pos
inputX = GetMouseX();
inputY = GetMouseY();
}
for(int i=0;i<4;i++)
{ {
//test distance each collider and input < radius // Use mouse position
if( fabsf(dpadCollider[i][1]-inputY) + fabsf(dpadCollider[i][0]-inputX) < dpadRad) inputPosition = GetMousePosition();
{
dpadKeydown = i;
break;
}
} }
// move player
switch(dpadKeydown){ // Reset pressed button to none
case 0: playerY -= 50*GetFrameTime(); pressedButton = BUTTON_NONE;
break;
case 1: playerX -= 50*GetFrameTime(); // Make sure user is pressing left mouse button if they're from desktop
break; if ((GetTouchPointCount() > 0) || ((GetTouchPointCount() == 0) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)))
case 2: playerX += 50*GetFrameTime(); {
break; // Find nearest D-Pad button to the input position
case 3: playerY += 50*GetFrameTime(); for (int i = 0; i < BUTTON_MAX; i++)
default:;
};
//--------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for(int i=0;i<4;i++)
{ {
//draw all pad float distX = fabsf(buttonPositions[i].x - inputPosition.x);
DrawCircleV((Vector2) { dpadCollider[i][0], dpadCollider[i][1] }, dpadRad, dpadColor); float distY = fabsf(buttonPositions[i].y - inputPosition.y);
if(i!=dpadKeydown)
if ((distX + distY < buttonRadius))
{ {
//draw label pressedButton = i;
DrawText(TextSubtext(dpadLabel,i,1), break;
(int)dpadCollider[i][0]-7,
(int)dpadCollider[i][1]-8,20,BLACK);
} }
} }
}
// Move player according to pressed button
switch (pressedButton)
{
case BUTTON_UP:
{
playerPosition.y -= playerSpeed*GetFrameTime();
break;
}
case BUTTON_LEFT:
{
playerPosition.x -= playerSpeed*GetFrameTime();
break;
}
case BUTTON_RIGHT:
{
playerPosition.x += playerSpeed*GetFrameTime();
break;
}
case BUTTON_DOWN:
{
playerPosition.y += playerSpeed*GetFrameTime();
break;
}
default: break;
};
//--------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw world
DrawCircleV(playerPosition, 50, MAROON);
// Draw GUI
for (int i = 0; i < BUTTON_MAX; i++)
{
DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton)? DARKGRAY : BLACK);
DrawText(buttonLabels[i],
(int)buttonPositions[i].x - 7, (int)buttonPositions[i].y - 8,
20, buttonLabelColors[i]);
}
DrawText("move the player with D-Pad buttons", 10, 10, 20, DARKGRAY);
DrawRectangleRec((Rectangle) { playerX - 4, playerY - 4, 75, 28 }, RED);
DrawText("Player", (int)playerX, (int)playerY, 20, WHITE);
EndDrawing(); EndDrawing();
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,6 +1,6 @@
#version 100 #version 100
precision highp float; precision highp float;
#define MAX_LIGHTS 4 #define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0 #define LIGHT_DIRECTIONAL 0
@ -24,7 +24,6 @@ varying vec3 fragNormal;
varying vec4 shadowPos; varying vec4 shadowPos;
varying mat3 TBN; varying mat3 TBN;
// Input uniform values // Input uniform values
uniform int numOfLights; uniform int numOfLights;
uniform sampler2D albedoMap; uniform sampler2D albedoMap;

View File

@ -1,11 +1,11 @@
#version 100 #version 100
// Input vertex attributes // Input vertex attributes
attribute vec3 vertexPosition; attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord; attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal; attribute vec3 vertexNormal;
attribute vec3 vertexTangent; attribute vec3 vertexTangent;
attribute vec4 vertexColor; attribute vec4 vertexColor;
// Input uniform values // Input uniform values
uniform mat4 mvp; uniform mat4 mvp;

View File

@ -25,7 +25,7 @@ void main()
// Send vertex attributes to fragment shader // Send vertex attributes to fragment shader
fragPosition = vec3(instanceTransform*vec4(vertexPosition, 1.0)); fragPosition = vec3(instanceTransform*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord; fragTexCoord = vertexTexCoord;
//fragColor = vertexColor; fragColor = vec4(1.0);
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0))); fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
// Calculate final vertex position, note that we multiply mvp by instanceTransform // Calculate final vertex position, note that we multiply mvp by instanceTransform

View File

@ -95,11 +95,19 @@ int main(void)
rlEnableFramebuffer(gBuffer.framebuffer); rlEnableFramebuffer(gBuffer.framebuffer);
// Since we are storing position and normal data in these textures, // NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture
// we need to use a floating point format. // (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position,
gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1); // depth, and the inverse view/projection matrices.
// 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios.
// But as mentioned above, the positions could be reconstructed instead of stored. If not targeting OpenGL ES
// and you wish to maintain this approach, consider using `RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32`.
gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility.
// This is generally sufficient, but a 16-bit fixed-point format offer a better uniform precision in all orientations.
gBuffer.normalTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
gBuffer.normalTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1);
// Albedo (diffuse color) and specular strength can be combined into one texture. // Albedo (diffuse color) and specular strength can be combined into one texture.
// The color in RGB, and the specular strength in the alpha channel. // The color in RGB, and the specular strength in the alpha channel.
gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);

View File

@ -61,7 +61,7 @@ int main(void)
{ {
Matrix translation = MatrixTranslate((float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50)); Matrix translation = MatrixTranslate((float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50), (float)GetRandomValue(-50, 50));
Vector3 axis = Vector3Normalize((Vector3){ (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360) }); Vector3 axis = Vector3Normalize((Vector3){ (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360), (float)GetRandomValue(0, 360) });
float angle = (float)GetRandomValue(0, 10)*DEG2RAD; float angle = (float)GetRandomValue(0, 180)*DEG2RAD;
Matrix rotation = MatrixRotate(axis, angle); Matrix rotation = MatrixRotate(axis, angle);
transforms[i] = MatrixMultiply(rotation, translation); transforms[i] = MatrixMultiply(rotation, translation);
@ -73,7 +73,6 @@ int main(void)
// Get shader locations // Get shader locations
shader.locs[SHADER_LOC_MATRIX_MVP] = GetShaderLocation(shader, "mvp"); shader.locs[SHADER_LOC_MATRIX_MVP] = GetShaderLocation(shader, "mvp");
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos"); shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocationAttrib(shader, "instanceTransform");
// Set shader value: ambient light level // Set shader value: ambient light level
int ambientLoc = GetShaderLocation(shader, "ambient"); int ambientLoc = GetShaderLocation(shader, "ambient");

View File

@ -2543,6 +2543,11 @@
"name": "SHADER_LOC_BONE_MATRICES", "name": "SHADER_LOC_BONE_MATRICES",
"value": 28, "value": 28,
"description": "Shader location: array of matrices uniform: boneMatrices" "description": "Shader location: array of matrices uniform: boneMatrices"
},
{
"name": "SHADER_LOC_VERTEX_INSTANCE_TX",
"value": 29,
"description": "Shader location: vertex attribute: instanceTransform"
} }
] ]
}, },
@ -2591,8 +2596,28 @@
"description": "Shader uniform type: ivec4 (4 int)" "description": "Shader uniform type: ivec4 (4 int)"
}, },
{ {
"name": "SHADER_UNIFORM_SAMPLER2D", "name": "SHADER_UNIFORM_UINT",
"value": 8, "value": 8,
"description": "Shader uniform type: unsigned int"
},
{
"name": "SHADER_UNIFORM_UIVEC2",
"value": 9,
"description": "Shader uniform type: uivec2 (2 unsigned int)"
},
{
"name": "SHADER_UNIFORM_UIVEC3",
"value": 10,
"description": "Shader uniform type: uivec3 (3 unsigned int)"
},
{
"name": "SHADER_UNIFORM_UIVEC4",
"value": 11,
"description": "Shader uniform type: uivec4 (4 unsigned int)"
},
{
"name": "SHADER_UNIFORM_SAMPLER2D",
"value": 12,
"description": "Shader uniform type: sampler2d" "description": "Shader uniform type: sampler2d"
} }
] ]
@ -4881,6 +4906,17 @@
"description": "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty", "description": "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty",
"returnType": "int" "returnType": "int"
}, },
{
"name": "GetKeyName",
"description": "Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)",
"returnType": "const char *",
"params": [
{
"type": "int",
"name": "key"
}
]
},
{ {
"name": "SetExitKey", "name": "SetExitKey",
"description": "Set a custom key to exit program (default is ESC)", "description": "Set a custom key to exit program (default is ESC)",
@ -9765,7 +9801,7 @@
}, },
{ {
"name": "TextToInteger", "name": "TextToInteger",
"description": "Get integer value from text (negative values not supported)", "description": "Get integer value from text",
"returnType": "int", "returnType": "int",
"params": [ "params": [
{ {
@ -9776,7 +9812,7 @@
}, },
{ {
"name": "TextToFloat", "name": "TextToFloat",
"description": "Get float value from text (negative values not supported)", "description": "Get float value from text",
"returnType": "float", "returnType": "float",
"params": [ "params": [
{ {

View File

@ -2543,6 +2543,11 @@ return {
name = "SHADER_LOC_BONE_MATRICES", name = "SHADER_LOC_BONE_MATRICES",
value = 28, value = 28,
description = "Shader location: array of matrices uniform: boneMatrices" description = "Shader location: array of matrices uniform: boneMatrices"
},
{
name = "SHADER_LOC_VERTEX_INSTANCE_TX",
value = 29,
description = "Shader location: vertex attribute: instanceTransform"
} }
} }
}, },
@ -2591,8 +2596,28 @@ return {
description = "Shader uniform type: ivec4 (4 int)" description = "Shader uniform type: ivec4 (4 int)"
}, },
{ {
name = "SHADER_UNIFORM_SAMPLER2D", name = "SHADER_UNIFORM_UINT",
value = 8, value = 8,
description = "Shader uniform type: unsigned int"
},
{
name = "SHADER_UNIFORM_UIVEC2",
value = 9,
description = "Shader uniform type: uivec2 (2 unsigned int)"
},
{
name = "SHADER_UNIFORM_UIVEC3",
value = 10,
description = "Shader uniform type: uivec3 (3 unsigned int)"
},
{
name = "SHADER_UNIFORM_UIVEC4",
value = 11,
description = "Shader uniform type: uivec4 (4 unsigned int)"
},
{
name = "SHADER_UNIFORM_SAMPLER2D",
value = 12,
description = "Shader uniform type: sampler2d" description = "Shader uniform type: sampler2d"
} }
} }
@ -4326,6 +4351,14 @@ return {
description = "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty", description = "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty",
returnType = "int" returnType = "int"
}, },
{
name = "GetKeyName",
description = "Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)",
returnType = "const char *",
params = {
{type = "int", name = "key"}
}
},
{ {
name = "SetExitKey", name = "SetExitKey",
description = "Set a custom key to exit program (default is ESC)", description = "Set a custom key to exit program (default is ESC)",
@ -6936,7 +6969,7 @@ return {
}, },
{ {
name = "TextToInteger", name = "TextToInteger",
description = "Get integer value from text (negative values not supported)", description = "Get integer value from text",
returnType = "int", returnType = "int",
params = { params = {
{type = "const char *", name = "text"} {type = "const char *", name = "text"}
@ -6944,7 +6977,7 @@ return {
}, },
{ {
name = "TextToFloat", name = "TextToFloat",
description = "Get float value from text (negative values not supported)", description = "Get float value from text",
returnType = "float", returnType = "float",
params = { params = {
{type = "const char *", name = "text"} {type = "const char *", name = "text"}

File diff suppressed because it is too large Load Diff

View File

@ -507,7 +507,7 @@
<Value name="MATERIAL_MAP_PREFILTER" integer="9" desc="Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)" /> <Value name="MATERIAL_MAP_PREFILTER" integer="9" desc="Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)" />
<Value name="MATERIAL_MAP_BRDF" integer="10" desc="Brdf material" /> <Value name="MATERIAL_MAP_BRDF" integer="10" desc="Brdf material" />
</Enum> </Enum>
<Enum name="ShaderLocationIndex" valueCount="29" desc="Shader location index"> <Enum name="ShaderLocationIndex" valueCount="30" desc="Shader location index">
<Value name="SHADER_LOC_VERTEX_POSITION" integer="0" desc="Shader location: vertex attribute: position" /> <Value name="SHADER_LOC_VERTEX_POSITION" integer="0" desc="Shader location: vertex attribute: position" />
<Value name="SHADER_LOC_VERTEX_TEXCOORD01" integer="1" desc="Shader location: vertex attribute: texcoord01" /> <Value name="SHADER_LOC_VERTEX_TEXCOORD01" integer="1" desc="Shader location: vertex attribute: texcoord01" />
<Value name="SHADER_LOC_VERTEX_TEXCOORD02" integer="2" desc="Shader location: vertex attribute: texcoord02" /> <Value name="SHADER_LOC_VERTEX_TEXCOORD02" integer="2" desc="Shader location: vertex attribute: texcoord02" />
@ -537,8 +537,9 @@
<Value name="SHADER_LOC_VERTEX_BONEIDS" integer="26" desc="Shader location: vertex attribute: boneIds" /> <Value name="SHADER_LOC_VERTEX_BONEIDS" integer="26" desc="Shader location: vertex attribute: boneIds" />
<Value name="SHADER_LOC_VERTEX_BONEWEIGHTS" integer="27" desc="Shader location: vertex attribute: boneWeights" /> <Value name="SHADER_LOC_VERTEX_BONEWEIGHTS" integer="27" desc="Shader location: vertex attribute: boneWeights" />
<Value name="SHADER_LOC_BONE_MATRICES" integer="28" desc="Shader location: array of matrices uniform: boneMatrices" /> <Value name="SHADER_LOC_BONE_MATRICES" integer="28" desc="Shader location: array of matrices uniform: boneMatrices" />
<Value name="SHADER_LOC_VERTEX_INSTANCE_TX" integer="29" desc="Shader location: vertex attribute: instanceTransform" />
</Enum> </Enum>
<Enum name="ShaderUniformDataType" valueCount="9" desc="Shader uniform data type"> <Enum name="ShaderUniformDataType" valueCount="13" desc="Shader uniform data type">
<Value name="SHADER_UNIFORM_FLOAT" integer="0" desc="Shader uniform type: float" /> <Value name="SHADER_UNIFORM_FLOAT" integer="0" desc="Shader uniform type: float" />
<Value name="SHADER_UNIFORM_VEC2" integer="1" desc="Shader uniform type: vec2 (2 float)" /> <Value name="SHADER_UNIFORM_VEC2" integer="1" desc="Shader uniform type: vec2 (2 float)" />
<Value name="SHADER_UNIFORM_VEC3" integer="2" desc="Shader uniform type: vec3 (3 float)" /> <Value name="SHADER_UNIFORM_VEC3" integer="2" desc="Shader uniform type: vec3 (3 float)" />
@ -547,7 +548,11 @@
<Value name="SHADER_UNIFORM_IVEC2" integer="5" desc="Shader uniform type: ivec2 (2 int)" /> <Value name="SHADER_UNIFORM_IVEC2" integer="5" desc="Shader uniform type: ivec2 (2 int)" />
<Value name="SHADER_UNIFORM_IVEC3" integer="6" desc="Shader uniform type: ivec3 (3 int)" /> <Value name="SHADER_UNIFORM_IVEC3" integer="6" desc="Shader uniform type: ivec3 (3 int)" />
<Value name="SHADER_UNIFORM_IVEC4" integer="7" desc="Shader uniform type: ivec4 (4 int)" /> <Value name="SHADER_UNIFORM_IVEC4" integer="7" desc="Shader uniform type: ivec4 (4 int)" />
<Value name="SHADER_UNIFORM_SAMPLER2D" integer="8" desc="Shader uniform type: sampler2d" /> <Value name="SHADER_UNIFORM_UINT" integer="8" desc="Shader uniform type: unsigned int" />
<Value name="SHADER_UNIFORM_UIVEC2" integer="9" desc="Shader uniform type: uivec2 (2 unsigned int)" />
<Value name="SHADER_UNIFORM_UIVEC3" integer="10" desc="Shader uniform type: uivec3 (3 unsigned int)" />
<Value name="SHADER_UNIFORM_UIVEC4" integer="11" desc="Shader uniform type: uivec4 (4 unsigned int)" />
<Value name="SHADER_UNIFORM_SAMPLER2D" integer="12" desc="Shader uniform type: sampler2d" />
</Enum> </Enum>
<Enum name="ShaderAttributeDataType" valueCount="4" desc="Shader attribute data types"> <Enum name="ShaderAttributeDataType" valueCount="4" desc="Shader attribute data types">
<Value name="SHADER_ATTRIB_FLOAT" integer="0" desc="Shader attribute type: float" /> <Value name="SHADER_ATTRIB_FLOAT" integer="0" desc="Shader attribute type: float" />
@ -674,7 +679,7 @@
<Param type="unsigned int" name="frames" desc="" /> <Param type="unsigned int" name="frames" desc="" />
</Callback> </Callback>
</Callbacks> </Callbacks>
<Functions count="581"> <Functions count="582">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context"> <Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
@ -1181,6 +1186,9 @@
</Function> </Function>
<Function name="GetCharPressed" retType="int" paramCount="0" desc="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty"> <Function name="GetCharPressed" retType="int" paramCount="0" desc="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty">
</Function> </Function>
<Function name="GetKeyName" retType="const char *" paramCount="1" desc="Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)">
<Param type="int" name="key" desc="" />
</Function>
<Function name="SetExitKey" retType="void" paramCount="1" desc="Set a custom key to exit program (default is ESC)"> <Function name="SetExitKey" retType="void" paramCount="1" desc="Set a custom key to exit program (default is ESC)">
<Param type="int" name="key" desc="" /> <Param type="int" name="key" desc="" />
</Function> </Function>
@ -2479,10 +2487,10 @@
<Function name="TextToCamel" retType="const char *" paramCount="1" desc="Get Camel case notation version of provided string"> <Function name="TextToCamel" retType="const char *" paramCount="1" desc="Get Camel case notation version of provided string">
<Param type="const char *" name="text" desc="" /> <Param type="const char *" name="text" desc="" />
</Function> </Function>
<Function name="TextToInteger" retType="int" paramCount="1" desc="Get integer value from text (negative values not supported)"> <Function name="TextToInteger" retType="int" paramCount="1" desc="Get integer value from text">
<Param type="const char *" name="text" desc="" /> <Param type="const char *" name="text" desc="" />
</Function> </Function>
<Function name="TextToFloat" retType="float" paramCount="1" desc="Get float value from text (negative values not supported)"> <Function name="TextToFloat" retType="float" paramCount="1" desc="Get float value from text">
<Param type="const char *" name="text" desc="" /> <Param type="const char *" name="text" desc="" />
</Function> </Function>
<Function name="DrawLine3D" retType="void" paramCount="3" desc="Draw a line in 3D world space"> <Function name="DrawLine3D" retType="void" paramCount="3" desc="Draw a line in 3D world space">

View File

@ -216,6 +216,7 @@ RLAPI bool IsKeyUp(int key); // Check if a key
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 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

View File

@ -693,16 +693,12 @@ Global
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x64.ActiveCfg = Debug|x64 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x64.ActiveCfg = Debug|x64
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x64.Build.0 = Debug|x64
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x86.ActiveCfg = Debug|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x86.ActiveCfg = Debug|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Debug|x86.Build.0 = Debug|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x86.Build.0 = Release.DLL|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x64.ActiveCfg = Release|x64 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x64.ActiveCfg = Release|x64
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x64.Build.0 = Release|x64
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x86.ActiveCfg = Release|Win32 {F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x86.ActiveCfg = Release|Win32
{F026020F-7B00-40C8-91C3-5DE85EC45A95}.Release|x86.Build.0 = Release|Win32
{6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 {6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
{6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 {6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
{6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 {6B8BAAF1-75C7-4C68-80B8-0E2A9EABBD9A}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32

View File

@ -23,6 +23,7 @@ endif()
# Used as public API to be included into other projects # Used as public API to be included into other projects
set(raylib_public_headers set(raylib_public_headers
raylib.h raylib.h
rcamera.h
rlgl.h rlgl.h
raymath.h raymath.h
) )
@ -90,16 +91,7 @@ if (BUILD_SHARED_LIBS)
set_property(TARGET raylib PROPERTY C_VISIBILITY_PRESET hidden) set_property(TARGET raylib PROPERTY C_VISIBILITY_PRESET hidden)
endif () endif ()
target_link_libraries(raylib "${LIBS_PRIVATE}")
# If building as a static lib *AND* using internal GLFW we
# need to set it up as a PRIVATE import so cmake doesn't complain
# it isn't declared on an install rule
if (INTERNAL_GLFW AND BUILD_SHARED_LIBS)
target_link_libraries(raylib PRIVATE glfw)
endif()
target_link_libraries(raylib PUBLIC "${LIBS_PRIVATE}")
# Sets some compile time definitions for the pre-processor # Sets some compile time definitions for the pre-processor
# If CUSTOMIZE_BUILD option is on you will not use config.h by default # If CUSTOMIZE_BUILD option is on you will not use config.h by default

View File

@ -61,11 +61,10 @@
#------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------
# Define target platform # Define target platform
PLATFORM ?= PLATFORM_DESKTOP PLATFORM ?= PLATFORM_DESKTOP
ifeq ($(PLATFORM), PLATFORM_DESKTOP) ifeq ($(PLATFORM), PLATFORM_DESKTOP)
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW
else else
TARGET_PLATFORM = $(PLATFORM) TARGET_PLATFORM = $(PLATFORM)
endif endif
# Define required raylib variables # Define required raylib variables
@ -122,7 +121,6 @@ SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include
SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib
SDL_LIBRARIES ?= -lSDL2 -lSDL2main SDL_LIBRARIES ?= -lSDL2 -lSDL2main
# Determine if the file has root access (only required to install raylib) # Determine if the file has root access (only required to install raylib)
# "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root") # "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root")
ROOT = $(shell whoami) ROOT = $(shell whoami)
@ -664,8 +662,8 @@ 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 #$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc
$(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(OBJS) $(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(OBJS)
@echo "raylib library generated (lib$(RAYLIB_LIB_NAME).a)!" @echo "raylib library generated (lib$(RAYLIB_LIB_NAME).web.a)!"
else else
ifeq ($(RAYLIB_LIBTYPE),SHARED) ifeq ($(RAYLIB_LIBTYPE),SHARED)
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW))

View File

@ -151,6 +151,8 @@
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif #endif
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
// Default shader vertex attribute names to set location points // Default shader vertex attribute names to set location points
// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience

661
src/external/RGFW.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -627,7 +627,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
} }
// Set mouse position XY // Set mouse position XY
@ -699,7 +699,7 @@ void PollInputEvents(void)
// Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll // Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
// NOTE: Activity is paused if not enabled (platform.appEnabled) // NOTE: Activity is paused if not enabled (platform.appEnabled)
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT) while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
{ {
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
@ -786,7 +786,7 @@ int InitPlatform(void)
while (!CORE.Window.ready) while (!CORE.Window.ready)
{ {
// Process events until we reach TIMEOUT, which indicates no more events queued. // Process events until we reach TIMEOUT, which indicates no more events queued.
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT) while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
{ {
// Process this event // Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source); if (platform.source != NULL) platform.source->process(platform.app, platform.source);
@ -1226,7 +1226,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
return 1; // Handled gamepad button return 1; // Handled gamepad button
} }
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)
{ {
// Save current key and its state // Save current key and its state

View File

@ -322,7 +322,7 @@ void SetWindowState(unsigned int flags)
} }
// State change: FLAG_FULLSCREEN_MODE // State change: FLAG_FULLSCREEN_MODE
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE)) if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
{ {
ToggleFullscreen(); // NOTE: Window state flag updated inside function ToggleFullscreen(); // NOTE: Window state flag updated inside function
} }
@ -1088,7 +1088,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform"); TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
} }
// Set mouse position XY // Set mouse position XY

View File

@ -129,6 +129,7 @@ static bool RGFW_disableCursor = false;
static const unsigned short keyMappingRGFW[] = { static const unsigned short keyMappingRGFW[] = {
[RGFW_KEY_NULL] = KEY_NULL, [RGFW_KEY_NULL] = KEY_NULL,
[RGFW_Return] = KEY_ENTER, [RGFW_Return] = KEY_ENTER,
[RGFW_Return] = KEY_ENTER,
[RGFW_Apostrophe] = KEY_APOSTROPHE, [RGFW_Apostrophe] = KEY_APOSTROPHE,
[RGFW_Comma] = KEY_COMMA, [RGFW_Comma] = KEY_COMMA,
[RGFW_Minus] = KEY_MINUS, [RGFW_Minus] = KEY_MINUS,
@ -168,7 +169,6 @@ static const unsigned short keyMappingRGFW[] = {
[RGFW_SuperL] = KEY_LEFT_SUPER, [RGFW_SuperL] = KEY_LEFT_SUPER,
#ifndef RGFW_MACOS #ifndef RGFW_MACOS
[RGFW_ShiftR] = KEY_RIGHT_SHIFT, [RGFW_ShiftR] = KEY_RIGHT_SHIFT,
[RGFW_AltR] = KEY_RIGHT_ALT, [RGFW_AltR] = KEY_RIGHT_ALT,
#endif #endif
[RGFW_Space] = KEY_SPACE, [RGFW_Space] = KEY_SPACE,
@ -496,7 +496,7 @@ void SetWindowIcons(Image *images, int count)
// Set title for window // Set title for window
void SetWindowTitle(const char *title) void SetWindowTitle(const char *title)
{ {
RGFW_window_setName(platform.window, (char*)title); RGFW_window_setName(platform.window, (char *)title);
CORE.Window.title = title; CORE.Window.title = title;
} }
@ -553,9 +553,9 @@ void SetWindowFocused(void)
void *GetWindowHandle(void) void *GetWindowHandle(void)
{ {
#ifdef RGFW_WEBASM #ifdef RGFW_WEBASM
return (void*)platform.window->src.ctx; return (void *)platform.window->src.ctx;
#else #else
return (void*)platform.window->src.window; return (void *)platform.window->src.window;
#endif #endif
} }
@ -598,7 +598,7 @@ Vector2 GetMonitorPosition(int monitor)
{ {
RGFW_monitor *mons = RGFW_getMonitors(); RGFW_monitor *mons = RGFW_getMonitors();
return (Vector2){(float)mons[monitor].rect.x, (float)mons[monitor].rect.y}; return (Vector2){ (float)mons[monitor].rect.x, (float)mons[monitor].rect.y };
} }
// Get selected monitor width (currently used by monitor) // Get selected monitor width (currently used by monitor)
@ -620,7 +620,7 @@ int GetMonitorHeight(int monitor)
// Get selected monitor physical width in millimetres // Get selected monitor physical width in millimetres
int GetMonitorPhysicalWidth(int monitor) int GetMonitorPhysicalWidth(int monitor)
{ {
RGFW_monitor* mons = RGFW_getMonitors(); RGFW_monitor *mons = RGFW_getMonitors();
return mons[monitor].physW; return mons[monitor].physW;
} }
@ -665,7 +665,7 @@ Vector2 GetWindowScaleDPI(void)
// Set clipboard text content // Set clipboard text content
void SetClipboardText(const char *text) void SetClipboardText(const char *text)
{ {
RGFW_writeClipboard(text, (u32)strlen(text)); RGFW_writeClipboard(text, strlen(text));
} }
// Get clipboard text content // Get clipboard text content
@ -685,19 +685,25 @@ const char *GetClipboardText(void)
# define WINGDI_ALREADY_INCLUDED # define WINGDI_ALREADY_INCLUDED
# include "../external/win32_clipboard.h" # include "../external/win32_clipboard.h"
#endif #endif
#endif
// Get clipboard image // Get clipboard image
Image GetClipboardImage(void) Image GetClipboardImage(void)
{ {
Image image = {0}; Image image = { 0 };
unsigned long long int dataSize = 0; unsigned long long int dataSize = 0;
void* fileData = NULL; void *fileData = NULL;
#ifdef _WIN32 #if defined(SUPPORT_CLIPBOARD_IMAGE)
int width, height; #if defined(_WIN32)
fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); int width = 0;
int height = 0;
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
else image = LoadImageFromMemory(".bmp", fileData, dataSize);
#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 #endif
if (fileData == NULL) if (fileData == NULL)
@ -742,9 +748,7 @@ void EnableCursor(void)
void DisableCursor(void) void DisableCursor(void)
{ {
RGFW_disableCursor = true; RGFW_disableCursor = true;
RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
HideCursor(); HideCursor();
} }
@ -794,6 +798,12 @@ int SetGamepadMappings(const char *mappings)
return 0; return 0;
} }
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
}
// Set mouse position XY // Set mouse position XY
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
@ -857,7 +867,6 @@ void PollInputEvents(void)
// Register previous mouse position // Register previous mouse position
// Reset last gamepad button/axis registered state // Reset last gamepad button/axis registered state
for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
{ {
// Check if gamepad is available // Check if gamepad is available
@ -1164,35 +1173,20 @@ int InitPlatform(void)
if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER; if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER;
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE; if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE;
if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW; if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW;
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN; if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN;
// 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
if (rlGetVersion() == RL_OPENGL_21) if (rlGetVersion() == RL_OPENGL_21) RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
{ else if (rlGetVersion() == RL_OPENGL_33) RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
RGFW_setGLVersion(RGFW_GL_CORE, 2, 1); else if (rlGetVersion() == RL_OPENGL_43) RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
}
else if (rlGetVersion() == RL_OPENGL_33)
{
RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
}
else if (rlGetVersion() == RL_OPENGL_43)
{
RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
}
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLSamples(4);
{
RGFW_setGLSamples(4);
}
platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
#ifndef PLATFORM_WEB_RGFW #ifndef PLATFORM_WEB_RGFW
RGFW_area screenSize = RGFW_getScreenSize(); RGFW_area screenSize = RGFW_getScreenSize();
CORE.Window.display.width = screenSize.w; CORE.Window.display.width = screenSize.w;
@ -1201,10 +1195,8 @@ int InitPlatform(void)
CORE.Window.display.width = CORE.Window.screen.width; CORE.Window.display.width = CORE.Window.screen.width;
CORE.Window.display.height = CORE.Window.screen.height; CORE.Window.display.height = CORE.Window.screen.height;
#endif #endif
/* // TODO: Is this needed by raylib now?
I think this is needed by Raylib now ? // If so, rcore_desktop_sdl should be updated too
If so, rcore_destkop_sdl should be updated too
*/
//SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); //SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
@ -1244,7 +1236,7 @@ int InitPlatform(void)
// Load OpenGL extensions // Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
rlLoadExtensions((void*)RGFW_getProcAddress); rlLoadExtensions((void *)RGFW_getProcAddress);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// TODO: Initialize input events system // TODO: Initialize input events system

View File

@ -23,7 +23,7 @@
* Custom flag for rcore on target platform -not used- * Custom flag for rcore on target platform -not used-
* *
* DEPENDENCIES: * DEPENDENCIES:
* - SDL 2 or SLD 3 (main library): Windowing and inputs management * - SDL 2 or SDL 3 (main library): Windowing and inputs management
* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) * - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
* *
* *
@ -68,7 +68,7 @@
#define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText() #define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText()
#endif #endif
#if ((defined(SDL_MAJOR_VERSION) && SDL_MAJOR_VERSION == 3) && (defined(SDL_MINOR_VERSION) && SDL_MINOR_VERSION >= 1)) #if ((defined(SDL_MAJOR_VERSION) && (SDL_MAJOR_VERSION == 3)) && (defined(SDL_MINOR_VERSION) && (SDL_MINOR_VERSION >= 1)))
#ifndef PLATFORM_DESKTOP_SDL3 #ifndef PLATFORM_DESKTOP_SDL3
#define PLATFORM_DESKTOP_SDL3 #define PLATFORM_DESKTOP_SDL3
#endif #endif
@ -405,7 +405,7 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
// Since SDL2 doesn't have this function we leave a stub // Since SDL2 doesn't have this function we leave a stub
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3) // SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
void* SDL_GetClipboardData(const char *mime_type, size_t *size) void *SDL_GetClipboardData(const char *mime_type, size_t *size)
{ {
TRACELOG(LOG_WARNING, "Getting clipboard data that is not text is only available in SDL3"); TRACELOG(LOG_WARNING, "Getting clipboard data that is not text is only available in SDL3");
@ -497,20 +497,21 @@ void ToggleBorderlessWindowed(void)
void MaximizeWindow(void) void MaximizeWindow(void)
{ {
SDL_MaximizeWindow(platform.window); SDL_MaximizeWindow(platform.window);
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
} }
// Set window state: minimized // Set window state: minimized
void MinimizeWindow(void) void MinimizeWindow(void)
{ {
SDL_MinimizeWindow(platform.window); SDL_MinimizeWindow(platform.window);
CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
} }
// Set window state: not minimized/maximized // Set window state: not minimized/maximized
void RestoreWindow(void) void RestoreWindow(void)
{ {
SDL_ShowWindow(platform.window); SDL_RestoreWindow(platform.window);
// CORE.Window.flags will be removed on PollInputEvents()
} }
// Set window configuration state using flags // Set window configuration state using flags
@ -1426,7 +1427,7 @@ void PollInputEvents(void)
// Window events are also polled (Minimized, maximized, close...) // Window events are also polled (Minimized, maximized, close...)
#ifndef PLATFORM_DESKTOP_SDL3 #ifndef PLATFORM_DESKTOP_SDL3
// SDL3 states: // SDL3 states:
// The SDL_WINDOWEVENT_* events have been moved to top level events, // The SDL_WINDOWEVENT_* events have been moved to top level events,
// and SDL_WINDOWEVENT has been removed. // and SDL_WINDOWEVENT has been removed.
@ -1436,7 +1437,7 @@ void PollInputEvents(void)
{ {
switch (event.window.event) switch (event.window.event)
{ {
#endif #endif
case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
{ {
@ -1448,7 +1449,24 @@ void PollInputEvents(void)
CORE.Window.currentFbo.width = width; CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height; CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true; CORE.Window.resizedLastFrame = true;
#ifndef PLATFORM_DESKTOP_SDL3
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms) to remove the FLAG_WINDOW_MAXIMIZED accordingly
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0)
{
int borderTop = 0;
int borderLeft = 0;
int borderBottom = 0;
int borderRight = 0;
SDL_GetWindowBordersSize(platform.window, &borderTop, &borderLeft, &borderBottom, &borderRight);
SDL_Rect usableBounds;
SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(platform.window), &usableBounds);
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
}
#endif
} break; } break;
case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_ENTER:
{ {
CORE.Input.Mouse.cursorOnScreen = true; CORE.Input.Mouse.cursorOnScreen = true;
@ -1457,16 +1475,49 @@ void PollInputEvents(void)
{ {
CORE.Input.Mouse.cursorOnScreen = false; CORE.Input.Mouse.cursorOnScreen = false;
} break; } break;
case SDL_WINDOWEVENT_HIDDEN:
case SDL_WINDOWEVENT_MINIMIZED: case SDL_WINDOWEVENT_MINIMIZED:
case SDL_WINDOWEVENT_FOCUS_LOST: {
case SDL_WINDOWEVENT_SHOWN: if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
case SDL_WINDOWEVENT_FOCUS_GAINED: } break;
case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_MAXIMIZED:
{
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
} break;
case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_RESTORED:
#if defined(PLATFORM_DESKTOP_SDL3) {
break; if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MINIMIZED) == 0)
#else {
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
}
#ifdef PLATFORM_DESKTOP_SDL3
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MAXIMIZED) == 0)
{
if ((CORE.Window.flags & SDL_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~SDL_WINDOW_MAXIMIZED;
}
#endif
} break;
case SDL_WINDOWEVENT_HIDDEN:
{
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) == 0) CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
} break;
case SDL_WINDOWEVENT_SHOWN:
{
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
} break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
} break;
case SDL_WINDOWEVENT_FOCUS_LOST:
{
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0) CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
} break;
#ifndef PLATFORM_DESKTOP_SDL3
default: break; default: break;
} }
} break; } break;
@ -1971,7 +2022,7 @@ void ClosePlatform(void)
// Scancode to keycode mapping // Scancode to keycode mapping
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode) static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
{ {
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM) if ((sdlScancode >= 0) && (sdlScancode < SCANCODE_MAPPED_NUM))
{ {
return mapScancodeToKey[sdlScancode]; return mapScancodeToKey[sdlScancode];
} }

View File

@ -622,7 +622,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration // Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{ {
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform"); TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
} }
// Set mouse position XY // Set mouse position XY
@ -1529,7 +1529,7 @@ static void ConfigureEvdevDevice(char *device)
platform.absRange.height = absinfo[ABS_Y].info.maximum - absinfo[ABS_Y].info.minimum; platform.absRange.height = absinfo[ABS_Y].info.maximum - absinfo[ABS_Y].info.minimum;
} }
} }
else if (isGamepad && !isMouse && !isKeyboard && platform.gamepadCount < MAX_GAMEPADS) else if (isGamepad && !isMouse && !isKeyboard && (platform.gamepadCount < MAX_GAMEPADS))
{ {
deviceKindStr = "gamepad"; deviceKindStr = "gamepad";
int index = platform.gamepadCount++; int index = platform.gamepadCount++;
@ -1893,7 +1893,7 @@ static int FindExactConnectorMode(const drmModeConnector *connector, uint width,
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive"); TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced)) continue; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced) continue;
if ((mode->hdisplay == width) && (mode->vdisplay == height) && (mode->vrefresh == fps)) return i; if ((mode->hdisplay == width) && (mode->vdisplay == height) && (mode->vrefresh == fps)) return i;
} }
@ -1923,7 +1923,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
continue; continue;
} }
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced)) if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced)
{ {
TRACELOG(LOG_TRACE, "DISPLAY: DRM shouldn't choose an interlaced mode"); TRACELOG(LOG_TRACE, "DISPLAY: DRM shouldn't choose an interlaced mode");
continue; continue;

View File

@ -381,6 +381,12 @@ int SetGamepadMappings(const char *mappings)
return 0; return 0;
} }
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
}
// Set mouse position XY // Set mouse position XY
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {

View File

@ -319,7 +319,7 @@ void ToggleBorderlessWindowed(void)
// Set window state: maximized, if resizable // Set window state: maximized, if resizable
void MaximizeWindow(void) void MaximizeWindow(void)
{ {
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED)) if ((glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
{ {
platform.unmaximizedWidth = CORE.Window.screen.width; platform.unmaximizedWidth = CORE.Window.screen.width;
platform.unmaximizedHeight = CORE.Window.screen.height; platform.unmaximizedHeight = CORE.Window.screen.height;
@ -342,7 +342,7 @@ void MinimizeWindow(void)
// Set window state: not minimized/maximized // Set window state: not minimized/maximized
void RestoreWindow(void) void RestoreWindow(void)
{ {
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED)) if ((glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
{ {
if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight); if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
@ -1664,10 +1664,10 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *
int height = EM_ASM_INT( return window.innerHeight; ); int height = EM_ASM_INT( return window.innerHeight; );
if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width; if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;
else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width; else if ((width > (int)CORE.Window.screenMax.width) && (CORE.Window.screenMax.width > 0)) width = CORE.Window.screenMax.width;
if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height; if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
else if (height > (int)CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height; else if ((height > (int)CORE.Window.screenMax.height) && (CORE.Window.screenMax.height > 0)) height = CORE.Window.screenMax.height;
emscripten_set_canvas_element_size("#canvas", width, height); emscripten_set_canvas_element_size("#canvas", width, height);
@ -1722,7 +1722,7 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]); for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
*/ */
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) if (gamepadEvent->connected && (gamepadEvent->index < MAX_GAMEPADS))
{ {
CORE.Input.Gamepad.ready[gamepadEvent->index] = true; CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index], "%s", gamepadEvent->id); sprintf(CORE.Input.Gamepad.name[gamepadEvent->index], "%s", gamepadEvent->id);

View File

@ -801,10 +801,10 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
wave.sampleRate = wav.sampleRate; wave.sampleRate = wav.sampleRate;
wave.sampleSize = 16; wave.sampleSize = 16;
wave.channels = wav.channels; wave.channels = wav.channels;
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short)); wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
// NOTE: We are forcing conversion to 16bit sample size on reading // NOTE: We are forcing conversion to 16bit sample size on reading
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data); drwav_read_pcm_frames_s16(&wav, wave.frameCount, wave.data);
} }
else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data"); else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data");
@ -1550,7 +1550,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0)) else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
{ {
// Open ogg audio stream // Open ogg audio stream
stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL); stb_vorbis *ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
if (ctxOgg != NULL) if (ctxOgg != NULL)
{ {
@ -2461,23 +2461,18 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut); float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
/* At this point we can convert the data to our mixing format. */ // At this point we can convert the data to our mixing format
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */ ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration);
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration; ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration); ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; /* Safe cast. */ totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) break; // Ran out of input data
{
break; /* Ran out of input data. */
}
/* This should never be hit, but will add it here for safety. Ensures we get out of the loop when no input nor output frames are processed. */ // This should never be hit, but added here for safety
if (inputFramesProcessedThisIteration == 0 && outputFramesProcessedThisIteration == 0) // Ensures we get out of the loop when no input nor output frames are processed
{ if ((inputFramesProcessedThisIteration == 0) && (outputFramesProcessedThisIteration == 0)) break;
break;
}
} }
return totalOutputFramesProcessed; return totalOutputFramesProcessed;

View File

@ -801,7 +801,8 @@ typedef enum {
SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices SHADER_LOC_BONE_MATRICES, // Shader location: array of matrices uniform: boneMatrices
SHADER_LOC_VERTEX_INSTANCE_TX // Shader location: vertex attribute: instanceTransform
} ShaderLocationIndex; } ShaderLocationIndex;
#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
@ -817,6 +818,10 @@ typedef enum {
SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
} ShaderUniformDataType; } ShaderUniformDataType;
@ -1150,20 +1155,19 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree() RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code RLAPI unsigned int 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)
// 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
RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set) RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Input Handling Functions (Module: core) // Input Handling Functions (Module: core)
@ -1177,19 +1181,20 @@ 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)
// 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
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
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 gamepad 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 axis 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)
// Input-related functions: mouse // Input-related functions: mouse
@ -1218,19 +1223,19 @@ 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 have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI int GetGestureDetected(void); // Get latest detected gesture
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in 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
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Camera System Functions (Module: rcamera) // Camera System Functions (Module: rcamera)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -1239,9 +1244,9 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f
// Set texture and rectangle to be used on shapes drawing // Set texture and rectangle to be used on shapes drawing
// NOTE: It can be useful when using basic shapes and one single font, // NOTE: It can be useful when using basic shapes and one single font,
// defining a font char white rectangle would allow drawing everything in a single draw call // defining a font char white rectangle would allow drawing everything in a single draw call
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
// Basic shapes drawing functions // Basic shapes drawing functions
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care] RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
@ -1283,11 +1288,11 @@ RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation
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
// Splines drawing functions // Splines drawing functions
RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points
RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points
RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
@ -1486,15 +1491,15 @@ RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint);
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
// Text codepoints management functions (unicode characters) // Text codepoints management functions (unicode characters)
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
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! // NOTE: Some strings allocate memory internally for returned strings, just be careful!
@ -1509,14 +1514,14 @@ RLAPI const char *TextJoin(const char **textList, int count, const char *delimit
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple 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!
RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) RLAPI int TextToInteger(const char *text); // Get integer value from text
RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported) 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)
@ -1609,14 +1614,14 @@ RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount);
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
// Collision detection functions // Collision detection functions
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio) // Audio Loading and Playing Functions (Module: audio)

View File

@ -328,8 +328,9 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
return result; return result;
} }
// Calculate angle between two vectors // Calculate the signed angle from v1 to v2, relative to the origin (0, 0)
// NOTE: Angle is calculated from origin point (0, 0) // NOTE: Coordinate system convention: positive X right, positive Y down,
// positive angles appear clockwise, and negative angles appear counterclockwise
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
{ {
float result = 0.0f; float result = 0.0f;
@ -2664,12 +2665,12 @@ inline const Vector2& operator *= (Vector2& lhs, const Matrix& rhs)
inline Vector2 operator / (const Vector2& lhs, const float& rhs) inline Vector2 operator / (const Vector2& lhs, const float& rhs)
{ {
return Vector2Scale(lhs, 1.0f / rhs); return Vector2Scale(lhs, 1.0f/rhs);
} }
inline const Vector2& operator /= (Vector2& lhs, const float& rhs) inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
{ {
lhs = Vector2Scale(lhs, 1.0f / rhs); lhs = Vector2Scale(lhs, 1.0f/rhs);
return lhs; return lhs;
} }
@ -2758,12 +2759,12 @@ inline const Vector3& operator *= (Vector3& lhs, const Matrix& rhs)
inline Vector3 operator / (const Vector3& lhs, const float& rhs) inline Vector3 operator / (const Vector3& lhs, const float& rhs)
{ {
return Vector3Scale(lhs, 1.0f / rhs); return Vector3Scale(lhs, 1.0f/rhs);
} }
inline const Vector3& operator /= (Vector3& lhs, const float& rhs) inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
{ {
lhs = Vector3Scale(lhs, 1.0f / rhs); lhs = Vector3Scale(lhs, 1.0f/rhs);
return lhs; return lhs;
} }
@ -2842,12 +2843,12 @@ inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
inline Vector4 operator / (const Vector4& lhs, const float& rhs) inline Vector4 operator / (const Vector4& lhs, const float& rhs)
{ {
return Vector4Scale(lhs, 1.0f / rhs); return Vector4Scale(lhs, 1.0f/rhs);
} }
inline const Vector4& operator /= (Vector4& lhs, const float& rhs) inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
{ {
lhs = Vector4Scale(lhs, 1.0f / rhs); lhs = Vector4Scale(lhs, 1.0f/rhs);
return lhs; return lhs;
} }

View File

@ -154,7 +154,7 @@ RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAr
RLAPI void CameraRoll(Camera *camera, float angle); RLAPI void CameraRoll(Camera *camera, float angle);
RLAPI Matrix GetCameraViewMatrix(Camera *camera); RLAPI Matrix GetCameraViewMatrix(Camera *camera);
RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect); RLAPI Matrix GetCameraProjectionMatrix(Camera *camera, float aspect);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -1355,6 +1355,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS); shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
// Get handles to GLSL uniform locations (vertex shader) // Get handles to GLSL uniform locations (vertex shader)
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
@ -2071,7 +2072,7 @@ const char *GetDirectoryPath(const char *filePath)
// In case provided path does not contain a root drive letter (C:\, D:\) nor leading path separator (\, /), // In case provided path does not contain a root drive letter (C:\, D:\) nor leading path separator (\, /),
// we add the current directory path to dirPath // we add the current directory path to dirPath
if (filePath[1] != ':' && filePath[0] != '\\' && filePath[0] != '/') if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/'))
{ {
// For security, we set starting path to current directory, // For security, we set starting path to current directory,
// obtained path will be concatenated to this // obtained path will be concatenated to this
@ -2774,7 +2775,8 @@ 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(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))))
static unsigned int hash[5] = { 0 }; // Hash to be returned static unsigned int hash[5] = { 0 }; // Hash to be returned
@ -2809,17 +2811,16 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
{ {
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int w[80] = {0}; unsigned int w[80] = {0};
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++)
w[i] = (msg[offset + (i * 4) + 0] << 24) | {
(msg[offset + (i * 4) + 1] << 16) | w[i] = (msg[offset + (i*4) + 0] << 24) |
(msg[offset + (i * 4) + 2] << 8) | (msg[offset + (i*4) + 1] << 16) |
(msg[offset + (i * 4) + 3]); (msg[offset + (i*4) + 2] << 8) |
(msg[offset + (i*4) + 3]);
} }
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words: // Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
for (int i = 16; i < 80; ++i) { for (int i = 16; i < 80; i++) w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
}
// Initialize hash value for this chunk // Initialize hash value for this chunk
unsigned int a = hash[0]; unsigned int a = hash[0];
@ -2833,16 +2834,23 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
unsigned int f = 0; unsigned int f = 0;
unsigned int k = 0; unsigned int k = 0;
if (i < 20) { if (i < 20)
{
f = (b & c) | ((~b) & d); f = (b & c) | ((~b) & d);
k = 0x5A827999; k = 0x5A827999;
} else if (i < 40) { }
else if (i < 40)
{
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0x6ED9EBA1; k = 0x6ED9EBA1;
} else if (i < 60) { }
else if (i < 60)
{
f = (b & c) | (b & d) | (c & d); f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC; k = 0x8F1BBCDC;
} else { }
else
{
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0xCA62C1D6; k = 0xCA62C1D6;
} }
@ -3324,7 +3332,8 @@ float GetGamepadAxisMovement(int gamepad, int axis)
{ {
float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f; float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) { if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS))
{
float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]); float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis]; if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis];

View File

@ -355,6 +355,9 @@
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
#endif #endif
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -998,6 +1001,9 @@ 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_NAME_BONEWEIGHTS #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#endif #endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
@ -1884,16 +1890,6 @@ void rlActiveDrawBuffers(int count)
else else
{ {
unsigned int buffers[8] = { unsigned int buffers[8] = {
#if defined(GRAPHICS_API_OPENGL_ES3)
GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT,
GL_COLOR_ATTACHMENT2_EXT,
GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,
GL_COLOR_ATTACHMENT5_EXT,
GL_COLOR_ATTACHMENT6_EXT,
GL_COLOR_ATTACHMENT7_EXT,
#else
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT2,
@ -1902,14 +1898,9 @@ void rlActiveDrawBuffers(int count)
GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT5,
GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT6,
GL_COLOR_ATTACHMENT7, GL_COLOR_ATTACHMENT7,
#endif
}; };
#if defined(GRAPHICS_API_OPENGL_ES3)
glDrawBuffersEXT(count, buffers);
#else
glDrawBuffers(count, buffers); glDrawBuffers(count, buffers);
#endif
} }
} }
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default"); else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
@ -3310,6 +3301,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
// Activate Trilinear filtering if mipmaps are available // Activate Trilinear filtering if mipmaps are available
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmapCount); // user defined mip count would break without this.
} }
#endif #endif
@ -3959,7 +3951,7 @@ void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
void rlDrawVertexArrayInstanced(int offset, int count, int instances) void rlDrawVertexArrayInstanced(int offset, int count, int instances)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances); glDrawArraysInstanced(GL_TRIANGLES, offset, count, instances);
#endif #endif
} }
@ -4216,6 +4208,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
#ifdef RL_SUPPORT_MESH_GPU_SKINNING #ifdef RL_SUPPORT_MESH_GPU_SKINNING
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);

View File

@ -96,9 +96,9 @@
#endif #endif
#if defined(SUPPORT_MESH_GENERATION) #if defined(SUPPORT_MESH_GENERATION)
#define PAR_MALLOC(T, N) ((T*)RL_MALLOC(N*sizeof(T))) #define PAR_MALLOC(T, N) ((T *)RL_MALLOC(N*sizeof(T)))
#define PAR_CALLOC(T, N) ((T*)RL_CALLOC(N*sizeof(T), 1)) #define PAR_CALLOC(T, N) ((T *)RL_CALLOC(N*sizeof(T), 1))
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N))) #define PAR_REALLOC(T, BUF, N) ((T *)RL_REALLOC(BUF, sizeof(T)*(N)))
#define PAR_FREE RL_FREE #define PAR_FREE RL_FREE
#if defined(_MSC_VER) // Disable some MSVC warning #if defined(_MSC_VER) // Disable some MSVC warning
@ -1734,12 +1734,12 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// no faster, since we're transferring all the transform matrices anyway // no faster, since we're transferring all the transform matrices anyway
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false); instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
// Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL // Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
for (unsigned int i = 0; i < 4; i++) for (unsigned int i = 0; i < 4; i++)
{ {
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i); rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4)); rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4));
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1); rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 1);
} }
rlDisableVertexBuffer(); rlDisableVertexBuffer();
@ -2270,38 +2270,60 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
{ {
if (frame >= anim.frameCount) frame = frame%anim.frameCount; if (frame >= anim.frameCount) frame = frame%anim.frameCount;
// Get first mesh which have bones
int firstMeshWithBones = -1;
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++)
{ {
if (model.meshes[i].boneMatrices) if (model.meshes[i].boneMatrices)
{ {
assert(model.meshes[i].boneCount == anim.boneCount); if (firstMeshWithBones == -1)
for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
{ {
Vector3 inTranslation = model.bindPose[boneId].translation; firstMeshWithBones = i;
Quaternion inRotation = model.bindPose[boneId].rotation; break;
Vector3 inScale = model.bindPose[boneId].scale; }
}
}
Vector3 outTranslation = anim.framePoses[frame][boneId].translation; // Update all bones and boneMatrices of first mesh with bones.
Quaternion outRotation = anim.framePoses[frame][boneId].rotation; for (int boneId = 0; boneId < anim.boneCount; boneId++)
Vector3 outScale = anim.framePoses[frame][boneId].scale; {
Vector3 inTranslation = model.bindPose[boneId].translation;
Quaternion inRotation = model.bindPose[boneId].rotation;
Vector3 inScale = model.bindPose[boneId].scale;
Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation)); Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
Quaternion invRotation = QuaternionInvert(inRotation); Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale); Vector3 outScale = anim.framePoses[frame][boneId].scale;
Vector3 boneTranslation = Vector3Add( Quaternion invRotation = QuaternionInvert(inRotation);
Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation), Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), invRotation);
outRotation), outTranslation); Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
Vector3 boneScale = Vector3Multiply(outScale, invScale);
Matrix boneMatrix = MatrixMultiply(MatrixMultiply( Vector3 boneTranslation = Vector3Add(Vector3RotateByQuaternion(
QuaternionToMatrix(boneRotation), Vector3Multiply(outScale, invTranslation), outRotation), outTranslation);
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)), Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
MatrixScale(boneScale.x, boneScale.y, boneScale.z)); Vector3 boneScale = Vector3Multiply(outScale, invScale);
model.meshes[i].boneMatrices[boneId] = boneMatrix; Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
QuaternionToMatrix(boneRotation),
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
MatrixScale(boneScale.x, boneScale.y, boneScale.z));
model.meshes[firstMeshWithBones].boneMatrices[boneId] = boneMatrix;
}
// Update remaining meshes with bones
// NOTE: Using deep copy because shallow copy results in double free with 'UnloadModel()'
if (firstMeshWithBones != -1)
{
for (int i = firstMeshWithBones + 1; i < model.meshCount; i++)
{
if (model.meshes[i].boneMatrices)
{
memcpy(model.meshes[i].boneMatrices,
model.meshes[firstMeshWithBones].boneMatrices,
model.meshes[i].boneCount*sizeof(model.meshes[i].boneMatrices[0]));
} }
} }
} }
@ -2314,6 +2336,7 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
{ {
UpdateModelAnimationBones(model,anim,frame); UpdateModelAnimationBones(model,anim,frame);
for (int m = 0; m < model.meshCount; m++) for (int m = 0; m < model.meshCount; m++)
{ {
Mesh mesh = model.meshes[m]; Mesh mesh = model.meshes[m];
@ -2322,8 +2345,12 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
int boneId = 0; int boneId = 0;
int boneCounter = 0; int boneCounter = 0;
float boneWeight = 0.0; float boneWeight = 0.0;
bool updated = false; // Flag to check when anim vertex information is updated bool updated = false; // Flag to check when anim vertex information is updated
const int vValues = mesh.vertexCount*3; const int vValues = mesh.vertexCount*3;
// Skip if missing bone data, causes segfault without on some models
if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue;
for (int vCounter = 0; vCounter < vValues; vCounter += 3) for (int vCounter = 0; vCounter < vValues; vCounter += 3)
{ {
mesh.animVertices[vCounter] = 0; mesh.animVertices[vCounter] = 0;
@ -2335,35 +2362,39 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
mesh.animNormals[vCounter + 1] = 0; mesh.animNormals[vCounter + 1] = 0;
mesh.animNormals[vCounter + 2] = 0; mesh.animNormals[vCounter + 2] = 0;
} }
// Iterates over 4 bones per vertex
// Iterates over 4 bones per vertex
for (int j = 0; j < 4; j++, boneCounter++) for (int j = 0; j < 4; j++, boneCounter++)
{ {
boneWeight = mesh.boneWeights[boneCounter]; boneWeight = mesh.boneWeights[boneCounter];
boneId = mesh.boneIds[boneCounter]; boneId = mesh.boneIds[boneCounter];
// Early stop when no transformation will be applied // Early stop when no transformation will be applied
if (boneWeight == 0.0f) continue; if (boneWeight == 0.0f) continue;
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]); animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]);
mesh.animVertices[vCounter] += animVertex.x * boneWeight; mesh.animVertices[vCounter] += animVertex.x*boneWeight;
mesh.animVertices[vCounter+1] += animVertex.y * boneWeight; mesh.animVertices[vCounter+1] += animVertex.y*boneWeight;
mesh.animVertices[vCounter+2] += animVertex.z * boneWeight; mesh.animVertices[vCounter+2] += animVertex.z*boneWeight;
updated = true; updated = true;
// Normals processing // Normals processing
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
if (mesh.normals != NULL) if ((mesh.normals != NULL) && (mesh.animNormals != NULL ))
{ {
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
animNormal = Vector3Transform(animNormal,model.meshes[m].boneMatrices[boneId]); animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model.meshes[m].boneMatrices[boneId])));
mesh.animNormals[vCounter] += animNormal.x*boneWeight; mesh.animNormals[vCounter] += animNormal.x*boneWeight;
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
} }
} }
} }
if (updated) if (updated)
{ {
rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position
rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals if (mesh.normals != NULL) rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
} }
} }
} }
@ -2725,11 +2756,11 @@ Mesh GenMeshCube(float width, float height, float length)
#else // Use par_shapes library to generate cube mesh #else // Use par_shapes library to generate cube mesh
/* /*
// Platonic solids: // Platonic solids:
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid) par_shapes_mesh *par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube) par_shapes_mesh *par_shapes_create_cube(); // 6 sides polyhedron (cube)
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond) par_shapes_mesh *par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron par_shapes_mesh *par_shapes_create_dodecahedron(); // 12 sides polyhedron
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron par_shapes_mesh *par_shapes_create_icosahedron(); // 20 sides polyhedron
*/ */
// Platonic solid generation: cube (6 sides) // Platonic solid generation: cube (6 sides)
// NOTE: No normals/texcoords generated by default // NOTE: No normals/texcoords generated by default
@ -3840,7 +3871,7 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
points[i] = Vector3Subtract(points[i], origin3D); points[i] = Vector3Subtract(points[i], origin3D);
if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD); if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation*DEG2RAD);
points[i] = Vector3Add(points[i], position); points[i] = Vector3Add(points[i], position);
} }
@ -4049,7 +4080,7 @@ RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)
for (int i = 0; i < triangleCount; i++) for (int i = 0; i < triangleCount; i++)
{ {
Vector3 a, b, c; Vector3 a, b, c;
Vector3* vertdata = (Vector3*)mesh.vertices; Vector3 *vertdata = (Vector3 *)mesh.vertices;
if (mesh.indices) if (mesh.indices)
{ {
@ -4190,30 +4221,27 @@ static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform
static Model LoadOBJ(const char *fileName) static Model LoadOBJ(const char *fileName)
{ {
tinyobj_attrib_t objAttributes = { 0 }; tinyobj_attrib_t objAttributes = { 0 };
tinyobj_shape_t* objShapes = NULL; tinyobj_shape_t *objShapes = NULL;
unsigned int objShapeCount = 0; unsigned int objShapeCount = 0;
tinyobj_material_t* objMaterials = NULL; tinyobj_material_t *objMaterials = NULL;
unsigned int objMaterialCount = 0; unsigned int objMaterialCount = 0;
Model model = { 0 }; Model model = { 0 };
model.transform = MatrixIdentity(); model.transform = MatrixIdentity();
char* fileText = LoadFileText(fileName); char *fileText = LoadFileText(fileName);
if (fileText == NULL) if (fileText == NULL)
{ {
TRACELOG(LOG_ERROR, "MODEL Unable to read obj file %s", fileName); TRACELOG(LOG_ERROR, "MODEL: [%s] Unable to read obj file", fileName);
return model; return model;
} }
char currentDir[1024] = { 0 }; char currentDir[1024] = { 0 };
strcpy(currentDir, GetWorkingDirectory()); // Save current working directory strcpy(currentDir, GetWorkingDirectory()); // Save current working directory
const char* workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
if (CHDIR(workingDir) != 0) if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
{
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
}
unsigned int dataSize = (unsigned int)strlen(fileText); unsigned int dataSize = (unsigned int)strlen(fileText);
@ -4222,7 +4250,7 @@ static Model LoadOBJ(const char *fileName)
if (ret != TINYOBJ_SUCCESS) if (ret != TINYOBJ_SUCCESS)
{ {
TRACELOG(LOG_ERROR, "MODEL Unable to read obj data %s", fileName); TRACELOG(LOG_ERROR, "MODEL: Unable to read obj data %s", fileName);
return model; return model;
} }
@ -4233,52 +4261,51 @@ static Model LoadOBJ(const char *fileName)
int lastMaterial = -1; int lastMaterial = -1;
unsigned int meshIndex = 0; unsigned int meshIndex = 0;
// count meshes // Count meshes
unsigned int nextShapeEnd = objAttributes.num_face_num_verts; unsigned int nextShapeEnd = objAttributes.num_face_num_verts;
// see how many verts till the next shape // See how many verts till the next shape
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset; if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
// walk all the faces // Walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{ {
if (faceId >= nextShapeEnd) if (faceId >= nextShapeEnd)
{ {
// try to find the last vert in the next shape // Try to find the last vert in the next shape
nextShape++; nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
meshIndex++; meshIndex++;
} }
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
{ {
meshIndex++;// if this is a new material, we need to allocate a new mesh meshIndex++; // If this is a new material, we need to allocate a new mesh
} }
lastMaterial = objAttributes.material_ids[faceId]; lastMaterial = objAttributes.material_ids[faceId];
faceVertIndex += objAttributes.face_num_verts[faceId]; faceVertIndex += objAttributes.face_num_verts[faceId];
} }
// allocate the base meshes and materials // Allocate the base meshes and materials
model.meshCount = meshIndex + 1; model.meshCount = meshIndex + 1;
model.meshes = (Mesh*)MemAlloc(sizeof(Mesh) * model.meshCount); model.meshes = (Mesh *)MemAlloc(sizeof(Mesh)*model.meshCount);
if (objMaterialCount > 0) if (objMaterialCount > 0)
{ {
model.materialCount = objMaterialCount; model.materialCount = objMaterialCount;
model.materials = (Material*)MemAlloc(sizeof(Material) * objMaterialCount); model.materials = (Material *)MemAlloc(sizeof(Material)*objMaterialCount);
} }
else // we must allocate at least one material else // We must allocate at least one material
{ {
model.materialCount = 1; model.materialCount = 1;
model.materials = (Material*)MemAlloc(sizeof(Material) * 1); model.materials = (Material *)MemAlloc(sizeof(Material)*1);
} }
model.meshMaterial = (int*)MemAlloc(sizeof(int) * model.meshCount); model.meshMaterial = (int *)MemAlloc(sizeof(int)*model.meshCount);
// see how many verts are in each mesh // See how many verts are in each mesh
unsigned int* localMeshVertexCounts = (unsigned int*)MemAlloc(sizeof(unsigned int) * model.meshCount); unsigned int *localMeshVertexCounts = (unsigned int *)MemAlloc(sizeof(unsigned int)*model.meshCount);
faceVertIndex = 0; faceVertIndex = 0;
nextShapeEnd = objAttributes.num_face_num_verts; nextShapeEnd = objAttributes.num_face_num_verts;
@ -4287,23 +4314,22 @@ static Model LoadOBJ(const char *fileName)
unsigned int localMeshVertexCount = 0; unsigned int localMeshVertexCount = 0;
nextShape = 1; nextShape = 1;
if (objShapeCount > 1) if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
nextShapeEnd = objShapes[nextShape].face_offset;
// walk all the faces // Walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{ {
bool newMesh = false; // do we need a new mesh? bool newMesh = false; // Do we need a new mesh?
if (faceId >= nextShapeEnd) if (faceId >= nextShapeEnd)
{ {
// try to find the last vert in the next shape // Try to find the last vert in the next shape
nextShape++; nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
newMesh = true; newMesh = true;
} }
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
{ {
newMesh = true; newMesh = true;
} }
@ -4321,50 +4347,52 @@ static Model LoadOBJ(const char *fileName)
faceVertIndex += objAttributes.face_num_verts[faceId]; faceVertIndex += objAttributes.face_num_verts[faceId];
localMeshVertexCount += objAttributes.face_num_verts[faceId]; localMeshVertexCount += objAttributes.face_num_verts[faceId];
} }
localMeshVertexCounts[meshIndex] = localMeshVertexCount; localMeshVertexCounts[meshIndex] = localMeshVertexCount;
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++)
{ {
// allocate the buffers for each mesh // Allocate the buffers for each mesh
unsigned int vertexCount = localMeshVertexCounts[i]; unsigned int vertexCount = localMeshVertexCounts[i];
model.meshes[i].vertexCount = vertexCount; model.meshes[i].vertexCount = vertexCount;
model.meshes[i].triangleCount = vertexCount / 3; model.meshes[i].triangleCount = vertexCount/3;
model.meshes[i].vertices = (float*)MemAlloc(sizeof(float) * vertexCount * 3); model.meshes[i].vertices = (float *)MemAlloc(sizeof(float)*vertexCount*3);
model.meshes[i].normals = (float*)MemAlloc(sizeof(float) * vertexCount * 3); model.meshes[i].normals = (float *)MemAlloc(sizeof(float)*vertexCount*3);
model.meshes[i].texcoords = (float*)MemAlloc(sizeof(float) * vertexCount * 2); model.meshes[i].texcoords = (float *)MemAlloc(sizeof(float)*vertexCount*2);
model.meshes[i].colors = (unsigned char*)MemAlloc(sizeof(unsigned char) * vertexCount * 4); model.meshes[i].colors = (unsigned char *)MemAlloc(sizeof(unsigned char)*vertexCount*4);
} }
MemFree(localMeshVertexCounts); MemFree(localMeshVertexCounts);
localMeshVertexCounts = NULL; localMeshVertexCounts = NULL;
// fill meshes // Fill meshes
faceVertIndex = 0; faceVertIndex = 0;
nextShapeEnd = objAttributes.num_face_num_verts; nextShapeEnd = objAttributes.num_face_num_verts;
// see how many verts till the next shape // See how many verts till the next shape
nextShape = 1; nextShape = 1;
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset; if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
lastMaterial = -1; lastMaterial = -1;
meshIndex = 0; meshIndex = 0;
localMeshVertexCount = 0; localMeshVertexCount = 0;
// walk all the faces // Walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{ {
bool newMesh = false; // do we need a new mesh? bool newMesh = false; // Do we need a new mesh?
if (faceId >= nextShapeEnd) if (faceId >= nextShapeEnd)
{ {
// try to find the last vert in the next shape // Try to find the last vert in the next shape
nextShape++; nextShape++;
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset; if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
newMesh = true; newMesh = true;
} }
// if this is a new material, we need to allocate a new mesh
// If this is a new material, we need to allocate a new mesh
if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true; if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;
lastMaterial = objAttributes.material_ids[faceId]; lastMaterial = objAttributes.material_ids[faceId];
@ -4375,8 +4403,7 @@ static Model LoadOBJ(const char *fileName)
} }
int matId = 0; int matId = 0;
if (lastMaterial >= 0 && lastMaterial < (int)objMaterialCount) if ((lastMaterial >= 0) && (lastMaterial < (int)objMaterialCount)) matId = lastMaterial;
matId = lastMaterial;
model.meshMaterial[meshIndex] = matId; model.meshMaterial[meshIndex] = matId;
@ -4386,19 +4413,15 @@ static Model LoadOBJ(const char *fileName)
int normalIndex = objAttributes.faces[faceVertIndex].vn_idx; int normalIndex = objAttributes.faces[faceVertIndex].vn_idx;
int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx; int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) model.meshes[meshIndex].vertices[localMeshVertexCount*3 + i] = objAttributes.vertices[vertIndex*3 + i];
model.meshes[meshIndex].vertices[localMeshVertexCount * 3 + i] = objAttributes.vertices[vertIndex * 3 + i];
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
model.meshes[meshIndex].normals[localMeshVertexCount * 3 + i] = objAttributes.normals[normalIndex * 3 + i];
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + i] = objAttributes.texcoords[texcordIndex * 2 + i];
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1]; model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++) model.meshes[meshIndex].colors[localMeshVertexCount*4 + i] = 255;
model.meshes[meshIndex].colors[localMeshVertexCount * 4 + i] = 255;
faceVertIndex++; faceVertIndex++;
localMeshVertexCount++; localMeshVertexCount++;
@ -4412,8 +4435,7 @@ static Model LoadOBJ(const char *fileName)
tinyobj_shapes_free(objShapes, objShapeCount); tinyobj_shapes_free(objShapes, objShapeCount);
tinyobj_materials_free(objMaterials, objMaterialCount); tinyobj_materials_free(objMaterials, objMaterialCount);
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++) UploadMesh(model.meshes + i, true);
UploadMesh(model.meshes + i, true);
// Restore current working directory // Restore current working directory
if (CHDIR(currentDir) != 0) if (CHDIR(currentDir) != 0)
@ -5069,6 +5091,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
{ {
Image image = { 0 }; Image image = { 0 };
if (cgltfImage == NULL) return image;
if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path) if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path)
{ {
if ((strlen(cgltfImage->uri) > 5) && if ((strlen(cgltfImage->uri) > 5) &&
@ -5110,7 +5134,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri)); image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));
} }
} }
else if (cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer else if (cgltfImage->buffer_view != NULL && cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer
{ {
unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size); unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size);
int offset = (int)cgltfImage->buffer_view->offset; int offset = (int)cgltfImage->buffer_view->offset;
@ -5664,7 +5688,7 @@ static Model LoadGLTF(const char *fileName)
} }
// Load primitive indices data (if provided) // Load primitive indices data (if provided)
if (mesh->primitives[p].indices != NULL) if ((mesh->primitives[p].indices != NULL) && (mesh->primitives[p].indices->buffer_view != NULL))
{ {
cgltf_accessor *attribute = mesh->primitives[p].indices; cgltf_accessor *attribute = mesh->primitives[p].indices;
@ -5681,7 +5705,7 @@ static Model LoadGLTF(const char *fileName)
else if (attribute->component_type == cgltf_component_type_r_8u) else if (attribute->component_type == cgltf_component_type_r_8u)
{ {
// Init raylib mesh indices to copy glTF attribute data // Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count * sizeof(unsigned short)); model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short) LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
} }
@ -5736,7 +5760,7 @@ static Model LoadGLTF(const char *fileName)
for (int i = 0; i < model.boneCount; i++) for (int i = 0; i < model.boneCount; i++)
{ {
cgltf_node* node = skin.joints[i]; cgltf_node *node = skin.joints[i];
cgltf_float worldTransform[16]; cgltf_float worldTransform[16];
cgltf_node_transform_world(node, worldTransform); cgltf_node_transform_world(node, worldTransform);
Matrix worldMatrix = { Matrix worldMatrix = {

View File

@ -247,7 +247,11 @@ extern void LoadFontDefault(void)
// we must consider data as little-endian order (alpha + gray) // we must consider data as little-endian order (alpha + gray)
((unsigned short *)imFont.data)[i + j] = 0xffff; ((unsigned short *)imFont.data)[i + j] = 0xffff;
} }
else ((unsigned short *)imFont.data)[i + j] = 0x00ff; else
{
((unsigned char *)imFont.data)[(i + j)*sizeof(short)] = 0xFF;
((unsigned char *)imFont.data)[(i + j)*sizeof(short) + 1] = 0x00;
}
} }
counter++; counter++;
@ -2325,9 +2329,9 @@ static Font LoadBMFont(const char *fileName)
// Convert hexadecimal to decimal (single digit) // Convert hexadecimal to decimal (single digit)
static unsigned char HexToInt(char hex) static unsigned char HexToInt(char hex)
{ {
if (hex >= '0' && hex <= '9') return hex - '0'; if ((hex >= '0') && (hex <= '9')) return hex - '0';
else if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10; else if ((hex >= 'a') && (hex <= 'f')) return hex - 'a' + 10;
else if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10; else if ((hex >= 'A') && (hex <= 'F')) return hex - 'A' + 10;
else return 0; else return 0;
} }

View File

@ -833,21 +833,18 @@ Image GenImageGradientLinear(int width, int height, int direction, Color start,
// bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient // bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient
// (i.e. the pixel which should become one of the gradient's ends color); while for // (i.e. the pixel which should become one of the gradient's ends color); while for
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0). // directions that lie in the second or fourth quadrant, that point is pixel (width, 0).
float maxPosValue = float maxPosValue = ((signbit(sinDir) != 0) == (signbit(cosDir) != 0))? fabsf(startingPos) : fabsf(startingPos + width*cosDir);
((signbit(sinDir) != 0) == (signbit(cosDir) != 0))
? fabsf(startingPos)
: fabsf(startingPos+width*cosDir);
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {
for (int j = 0; j < height; j++) for (int j = 0; j < height; j++)
{ {
// Calculate the relative position of the pixel along the gradient direction // Calculate the relative position of the pixel along the gradient direction
float pos = (startingPos + (i*cosDir + j*sinDir)) / maxPosValue; float pos = (startingPos + (i*cosDir + j*sinDir))/maxPosValue;
float factor = pos; float factor = pos;
factor = (factor > 1.0f)? 1.0f : factor; // Clamp to [-1,1] factor = (factor > 1.0f)? 1.0f : factor; // Clamp to [-1,1]
factor = (factor < -1.0f)? -1.0f : factor; // Clamp to [-1,1] factor = (factor < -1.0f)? -1.0f : factor; // Clamp to [-1,1]
factor = factor / 2 + 0.5f; factor = factor/2.0f + 0.5f;
// Generate the color for this pixel // Generate the color for this pixel
pixels[j*width + i].r = (int)((float)end.r*factor + (float)start.r*(1.0f - factor)); pixels[j*width + i].r = (int)((float)end.r*factor + (float)start.r*(1.0f - factor));
@ -1007,7 +1004,8 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float
{ {
Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color)); Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
float aspectRatio = (float)width / (float)height; float aspectRatio = (float)width/(float)height;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@ -3567,7 +3565,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co
ImageDrawLine(dst, x1, y1, x2, y2, color); ImageDrawLine(dst, x1, y1, x2, y2, color);
// Determine if the line is more horizontal or vertical // Determine if the line is more horizontal or vertical
if (dx != 0 && abs(dy/dx) < 1) if ((dx != 0) && (abs(dy/dx) < 1))
{ {
// Line is more horizontal // Line is more horizontal
// Calculate half the width of the line // Calculate half the width of the line
@ -4206,8 +4204,10 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
ImageFormat(&faces, image.format); ImageFormat(&faces, image.format);
Image mipmapped = ImageCopy(image); Image mipmapped = ImageCopy(image);
#if defined(SUPPORT_IMAGE_MANIPULATION)
ImageMipmaps(&mipmapped); ImageMipmaps(&mipmapped);
ImageMipmaps(&faces); ImageMipmaps(&faces);
#endif
// NOTE: Image formatting does not work with compressed textures // NOTE: Image formatting does not work with compressed textures
@ -5387,7 +5387,7 @@ static float HalfToFloat(unsigned short x)
const unsigned int e = (x & 0x7C00) >> 10; // Exponent const unsigned int e = (x & 0x7C00) >> 10; // Exponent
const unsigned int m = (x & 0x03FF) << 13; // Mantissa const unsigned int m = (x & 0x03FF) << 13; // Mantissa
const float fm = (float)m; const float fm = (float)m;
const unsigned int v = (*(unsigned int*)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format const unsigned int v = (*(unsigned int *)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
result = *(float *)&r; result = *(float *)&r;
@ -5400,7 +5400,7 @@ static unsigned short FloatToHalf(float x)
{ {
unsigned short result = 0; unsigned short result = 0;
const unsigned int b = (*(unsigned int*) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa const unsigned int b = (*(unsigned int *) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
const unsigned int e = (b & 0x7F800000) >> 23; // Exponent const unsigned int e = (b & 0x7F800000) >> 23; // Exponent
const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding